├── .gitattributes
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── distro-de-wm-shell-hw-request.md
│ └── install-issue.md
├── .gitignore
├── Examples
├── appleterm.png
├── gnometerm.png
├── hp.png
├── intelcpu.png
├── konsole.png
├── len.png
├── mac.png
├── pent.png
├── ryzencpu.png
├── tuf.png
├── ubuntu.png
└── windows.png
├── LICENSE
├── MANIFEST.in
├── README.md
├── discord.sh
├── fetch_cord.conf
├── fetch_cord
├── Cycle.py
├── Logger.py
├── __init__.py
├── __main__.py
├── args.py
├── computer
│ ├── Computer.py
│ ├── Peripheral_interface.py
│ ├── __init__.py
│ ├── cpu
│ │ ├── Cpu_amd.py
│ │ ├── Cpu_intel.py
│ │ ├── Cpu_interface.py
│ │ ├── __init__.py
│ │ └── get_cpu.py
│ ├── flatpak.py
│ ├── gpu
│ │ ├── Gpu_amd.py
│ │ ├── Gpu_intel.py
│ │ ├── Gpu_interface.py
│ │ ├── Gpu_nvidia.py
│ │ ├── __init__.py
│ │ └── get_gpu.py
│ ├── mobo
│ │ ├── __init__.py
│ │ └── get_mobo.py
│ └── resources.py
├── config.py
├── config_schema.json
├── cycles.py
├── debugger.py
├── resources
│ ├── __init__.py
│ ├── default.conf
│ ├── fetch_cord.conf
│ ├── fetchcord_ids.json
│ └── systemd_service.py
├── run_command.py
├── run_rpc.py
└── update.py
├── setup.py
├── snapcraft.yaml
├── systemd
└── fetchcord.service
└── tests
└── test_fetch_cord_computer.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | # Debug info
11 |
12 | **Please run `fetchcord --debug` and send it here.**
13 |
14 | **If you are unable to run FetchCord please run `neofetch --noart`(windows) or `neofetch -- stdout`(macos&linux)**
15 |
16 | # Operating system & way of installation
17 |
18 | **Please provide your operating system, and how you got FetchCord(AUR, github,pip) here**
19 |
20 | # Error/issue
21 |
22 | **Your error or bug report goes in here.**
23 |
24 | # Other notes(optional)
25 |
26 | **Other notes about the error/issue**
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/distro-de-wm-shell-hw-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Distro/de/wm/shell/hw request
3 | about: request to add a /de/wm/shell/hw
4 | title: ''
5 | labels: distro/wm/hardware/term request
6 | assignees: ''
7 |
8 | ---
9 |
10 | # Debug info
11 |
12 | **Please run `fetchcord --debug` and put it here. You might also want to send the output of `neofetch --noart`(windows) or `neofetch -- stdout`(macos&linux)**
13 |
14 | # Requested item
15 |
16 | **Here goes your desired os/de/wm/shell/hardware request**
17 |
18 | # Other notes
19 |
20 | **Other notes about the request go here**
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/install-issue.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Install issue
3 | about: Get help with installation issues
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | # How you tried to install fetchcord
11 |
12 | **This can be AUR, Github, or pip.**
13 |
14 | # Operating system
15 |
16 | **Your OS goes here.**
17 |
18 | # Other notes
19 |
20 | **Other notes about install error/issue.**
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # celery beat schedule file
95 | celerybeat-schedule
96 |
97 | # SageMath parsed files
98 | *.sage.py
99 |
100 | # Environments
101 | .env
102 | .venv
103 | env/
104 | venv/
105 | ENV/
106 | env.bak/
107 | venv.bak/
108 |
109 | # Spyder project settings
110 | .spyderproject
111 | .spyproject
112 |
113 | # Rope project settings
114 | .ropeproject
115 |
116 | # mkdocs documentation
117 | /site
118 |
119 | # mypy
120 | .mypy_cache/
121 | .dmypy.json
122 | dmypy.json
123 |
124 | # Pyre type checker
125 | .pyre/
126 | #pycharm file
127 | .idea
128 |
129 | # vim file
130 | .vim/
131 |
132 | # auth key
133 | authkey_pypi
134 | .DS_Store
135 |
136 | fctest.py
137 | .vscode
138 | samples
139 |
140 | # Snap
141 | *.snap
--------------------------------------------------------------------------------
/Examples/appleterm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/appleterm.png
--------------------------------------------------------------------------------
/Examples/gnometerm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/gnometerm.png
--------------------------------------------------------------------------------
/Examples/hp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/hp.png
--------------------------------------------------------------------------------
/Examples/intelcpu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/intelcpu.png
--------------------------------------------------------------------------------
/Examples/konsole.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/konsole.png
--------------------------------------------------------------------------------
/Examples/len.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/len.png
--------------------------------------------------------------------------------
/Examples/mac.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/mac.png
--------------------------------------------------------------------------------
/Examples/pent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/pent.png
--------------------------------------------------------------------------------
/Examples/ryzencpu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/ryzencpu.png
--------------------------------------------------------------------------------
/Examples/tuf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/tuf.png
--------------------------------------------------------------------------------
/Examples/ubuntu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/ubuntu.png
--------------------------------------------------------------------------------
/Examples/windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/Examples/windows.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 MrPotatoBobx
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 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include *.py
2 | include */*.py
3 | include */*/*.py
4 | include */*/*/*.py
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
FetchCord
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
19 |
20 | # Table of content
21 | - [**Features**](#features)
22 | - [**To-Do**](#to-do)
23 | + **Installing**
24 | - [Install on (gnu/)linux](#installing-on-gnulinux)
25 | - [Install on MacOS](#installing-on-macos)
26 | - [Install on Windows](#installing-on-windows)
27 | + **Running**
28 | - [Running on (gnu/)linux](#run)
29 | - [Running on MacOS](#run-1)
30 | - [Running on Windows](#run-2)
31 | - [**Configuration**](#Configuration)
32 | - [**Arguments**](#arguments)
33 | - [**Website**](#website)
34 |
35 | + [**Examples**](#examples)
36 |
37 | ### Features
38 |
39 | - [x] Distribution detection
40 |
41 | - [x] Distribution Version
42 |
43 | - [x] Package detection
44 |
45 | - [x] Kernel Detection
46 |
47 | - [x] Uptime
48 |
49 | - [x] Detecting Window Manager/Desktop Environment
50 |
51 | - [x] Detecting GPU/CPU and display it in a cycle (thanks to Hyper-KVM)
52 |
53 | - [x] Flatpak support
54 |
55 | - [x] Add Snap support
56 |
57 | - [x] Add Windows support.
58 |
59 | - [x] Detect Window Manager/Desktop Environment version
60 |
61 | - [x] Periodic polling of info such as package count, RAM usage, etc.
62 |
63 |
64 | ### To-Do
65 |
66 | - [ ] Add more distributions (If your distro is not supported open an issue)
67 |
68 | - [ ] Add support for desktop icon use
69 |
70 | - [ ] More CPUs, ex. Pentium, Older AMD CPUs
71 |
72 | - [ ] More GPUs?
73 |
74 |
75 | ## Installing on (GNU/)Linux
76 | NOTE: you need neofetch to be also installed for this to work.
77 | #### Via AUR
78 | On Arch Linux for the git testing version (the less stable version): [fetchcord-testing](https://aur.archlinux.org/packages/fetchcord-testing/)
79 |
80 | And the git version (synced with master): [fetchcord](https://aur.archlinux.org/packages/fetchcord/)
81 |
82 | Historically the stabler release was the one from [pip](#via-pip) but now master will have only the stable releases.
83 | #### Via Snap
84 | On systems with snap installed, you can run `sudo snap install fetchcord --classic` to install fetchcord.
85 |
86 | Note that like the AUR version, this version is directly from master, for the stable release use [pip](#via-pip)
87 | #### Via pip
88 | To Install fetchcord via pip you can run `pip3 install fetchcord`
89 |
90 | If you want to remove FetchCord you can run `pip3 uninstall fetchcord`
91 |
92 | ### Run
93 |
94 | Once installed, simply run `fetchcord`. The program is also daemonizable meaning you can start it on boot using any method you prefer.
95 |
96 | If you get `fetchcord: command not found`,add `export PATH="$HOME/.local/bin:$PATH"` to your bashrc, or just run `python3 -m fetchcord`.
97 |
98 | Optionally for systemd users there is a user-side `fetchcord.service` in this repo that can be installed to `~/.local/share/systemd/user/`, started and enabled on boot using `systemctl --user enable --now fetchcord`.
99 |
100 | ## Installing on MacOS
101 |
102 | To install FetchCord, run `pip3 install FetchCord`
103 |
104 | NOTE: you need neofetch to be also installed for this to work.
105 |
106 | ### Run
107 |
108 | simply run `fetchcord`
109 |
110 | ## Installing on Windows
111 |
112 | To install fetchcord on Windows run `python -m pip install fetchcord neofetch-win`. Alternatively, you can use the neofetch package from scoop as well (show more info at the expense of possible GPU detection, for now).
113 |
114 | ### Run
115 | To run Fetchcord run `fetchcord`
116 |
117 | ### Configuration
118 |
119 | On Linux you can use the neofetch config file to:
120 |
121 | Show disk usage
122 |
123 | Battery level
124 |
125 | CPU temp
126 |
127 | Current CPU speed
128 |
129 | Font
130 |
131 | Theme
132 |
133 | And more
134 |
135 | default config path should be `~/.config/neofetch/config.conf`
136 |
137 | ## Arguments
138 | --nodistro, Don't show distro info.
139 |
140 | --nohardware, Don't show hardware info.
141 |
142 | --noshell, Don't show shell/terminal info.
143 |
144 | --nohost, Don't show host info.
145 |
146 | --time, -t, set custom duration for cycles in seconds.
147 |
148 | --terminal, set custom terminal (useful if using a script or dmenu).
149 |
150 | --termfont, set custom terminal font (useful if neofetch can't get it).
151 |
152 | --pause-cycle, Extra cycle that pauses FetchCord to show other activities.
153 |
154 | --update, Update database of distros, hardware, etc.
155 |
156 | --debug, For debug logs.
157 |
158 | --memtype, use GB or MB to show RAM.
159 |
160 | -h or --help, shows this information above.
161 |
162 | ## Website
163 |
164 | Fetchcord now has a website! You can find this site over at https://fetchcord.github.io/ - please keep in mind this site is still currently work in progress though.
165 |
166 | ## Examples
167 |
168 | ### Operating Systems
169 |   
170 | ### Terminals
171 |   
172 | ### Cpus
173 |   
174 | ### Hosts
175 |   
176 |
--------------------------------------------------------------------------------
/discord.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | while true; do
3 | pid=$(ps ax | grep -i "fetchcord" | grep -v grep | awk '{print $1}')
4 | if [ ! -z "$pid" ]; then
5 | kill -15 $pid
6 | fi
7 | fetchcord &
8 | /opt/Discord/Discord &
9 | if [ $? -eq 0 ]; then
10 | exit
11 | fi
12 | sleep 25
13 | done
14 |
--------------------------------------------------------------------------------
/fetch_cord.conf:
--------------------------------------------------------------------------------
1 | [cycle_0]
2 |
3 | # Order to set info in discord presence, valid values are: kernel, packages
4 | top_line=kernel
5 | bottom_line=packages
6 | # show small_icon in Discord
7 | de_wm_icon=on
8 |
9 | # Duration to show this cycle
10 | # valid values are, 15, 30, 45, 60, 75, 90, 105, 120, 240, and 480
11 | time=30
12 |
13 | [cycle_1]
14 |
15 | # Order to set info in discord presence, valid values are: mem, gpu, cpu, and disk
16 | top_line=mem
17 | bottom_line=gpu
18 | # show small_icon in Discord
19 | gpu_icon=on
20 |
21 | # Duration to show this cycle
22 | # valid values are, 15, 30, 45, 60, 75, 90, 105, 120, 240, and 480
23 | time=30
24 |
25 | [cycle_2]
26 |
27 | # Order to set info in discord presence, valid values are: font, shell, and theme
28 | top_line=font
29 | bottom_line=shell
30 | # show small_icon in Discord
31 | shell_icon=on
32 |
33 | # Duration to show this cycle
34 | # valid values are, 15, 30, 45, 60, 75, 90, 105, 120, 240, and 480
35 | time=30
36 |
37 | [cycle_3]
38 |
39 | # Order to set info in discord presence, valid values are: battery, resolution, and host
40 | top_line=battery
41 | bottom_line=resolution
42 | # show small_icon in Discord
43 | lapordesk_icon=on
44 |
45 | # Duration to show this cycle
46 | # valid values are, 15, 30, 45, 60, 75, 90, 105, 120, 240, and 480
47 | time=30
48 |
--------------------------------------------------------------------------------
/fetch_cord/Cycle.py:
--------------------------------------------------------------------------------
1 | from .computer.Computer import Computer
2 | from typing import Dict
3 |
4 |
5 | class Cycle:
6 | name: str
7 |
8 | top_line: str = None
9 | bottom_line: str = None
10 | small_icon: str = None
11 |
12 | def __init__(self, name: str, config: Dict[str, str], computer: Computer):
13 | self.name = name
14 |
15 | if "top_line" in config["top_line"]:
16 | self.top_line = config["top_line"]
17 | if "bottom_line" in config["bottom_line"]:
18 | self.bottom_line = config["bottom_line"]
19 | if "small_icon" in config["small_icon"]:
20 | self.small_icon = config["small_icon"]
--------------------------------------------------------------------------------
/fetch_cord/Logger.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import logging
3 | from logging.handlers import TimedRotatingFileHandler
4 |
5 | class Logger(logging.Logger):
6 | FORMATTER = logging.Formatter(
7 | "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
8 | )
9 |
10 | file: str
11 | console_handler: logging.StreamHandler
12 | file_handler: TimedRotatingFileHandler
13 |
14 | def get_console_handler() -> logging.StreamHandler:
15 | console_handler = logging.StreamHandler(sys.stdout)
16 | console_handler.setFormatter(Logger.FORMATTER)
17 |
18 | return console_handler
19 |
20 | def get_file_handler(file: str) -> TimedRotatingFileHandler:
21 | file_handler = TimedRotatingFileHandler(file, when="midnight")
22 | file_handler.setFormatter(Logger.FORMATTER)
23 |
24 | return file_handler
25 |
26 | def __init__(self, file: str, name: str, level: int = logging.INFO):
27 | super().__init__(logging.getLogger(name))
28 |
29 | self.file = file
30 | self.console_handler = Logger.get_console_handler()
31 | self.file_handler = Logger.get_file_handler(file)
32 |
33 | self.setLevel(level)
34 | self.addHandler(self.console_handler)
35 | self.addHandler(self.file_handler)
36 |
37 | self.propagate = False
--------------------------------------------------------------------------------
/fetch_cord/__init__.py:
--------------------------------------------------------------------------------
1 | VERSION = "2.7.7"
--------------------------------------------------------------------------------
/fetch_cord/__main__.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 |
3 | from typing import Dict
4 | import sys, os
5 |
6 | from .run_rpc import Run_rpc
7 | from .cycles import cycle0, cycle1, cycle2, cycle3, runmac, windows, pause
8 | from .computer.Computer import Computer
9 | from .args import parse_args
10 | from .debugger import run_rpc_debug
11 | from .update import update
12 | from . import __init__ as __init__
13 | from .resources import systemd_service
14 |
15 |
16 | def main():
17 | args = parse_args()
18 |
19 | if args.update:
20 | update()
21 | if os.name != "nt" and sys.platform != "darwin":
22 | if args.install:
23 | systemd_service.install()
24 | if args.uninstall:
25 | systemd_service.uninstall()
26 | if args.enable:
27 | systemd_service.enable()
28 | if args.disable:
29 | systemd_service.disable()
30 | if args.start:
31 | systemd_service.start()
32 | if args.stop:
33 | systemd_service.stop()
34 | if args.status:
35 | systemd_service.status()
36 | if args.version:
37 | print("FetchCord version:", __init__.VERSION)
38 | sys.exit(0)
39 | if args.time:
40 | if int(args.time) < 15:
41 | print("ERROR: Invalid time set, must be > 15 seconds, cannot continue.")
42 | sys.exit(1)
43 | else:
44 | print("setting custom time %s seconds" % args.time)
45 | try:
46 | if args.help:
47 | sys.exit(0)
48 | except AttributeError:
49 | pass
50 |
51 | computer: Computer = Computer()
52 |
53 | if (
54 | not computer.neofetchwin
55 | and computer.host == "Host: N/A"
56 | and args.nodistro
57 | and args.noshell
58 | and args.nohardware
59 | ):
60 | print("ERROR: no hostline is available!")
61 | sys.exit(1)
62 | # printing info with debug switch
63 | if args.debug:
64 | run_rpc_debug(computer)
65 |
66 | run: Run_rpc = Run_rpc()
67 |
68 | if computer.neofetchwin:
69 | # wandowz
70 | loops: Dict = {}
71 | loops_indexes: Dict = {}
72 |
73 | if not args.nodistro:
74 | loops["windows"] = (computer.osinfoid, windows)
75 | loops_indexes[len(loops_indexes)] = "windows"
76 | if not args.nohardware:
77 | loops["cycle1"] = (computer.cpuid, cycle1)
78 | loops_indexes[len(loops_indexes)] = "cycle1"
79 |
80 | run.set_loop(
81 | loops,
82 | loops_indexes,
83 | computer.updateMap,
84 | int(args.poll_rate) if args.poll_rate else 3,
85 | )
86 | run.run_loop(computer)
87 | else:
88 | # loonix
89 | loops: Dict = {}
90 | loops_indexes: Dict = {}
91 |
92 | if not args.nodistro and computer.os != "macos":
93 | loops["cycle0"] = (computer.osinfoid, cycle0)
94 | loops_indexes[len(loops_indexes)] = "cycle0"
95 | if computer.os == "macos":
96 | loops["runmac"] = ("740822755376758944", runmac)
97 | loops_indexes[len(loops_indexes)] = "runmac"
98 | if not args.nohardware:
99 | loops["cycle1"] = (computer.cpuid, cycle1)
100 | loops_indexes[len(loops_indexes)] = "cycle1"
101 | if not args.noshell:
102 | loops["cycle2"] = (computer.terminalid, cycle2)
103 | loops_indexes[len(loops_indexes)] = "cycle2"
104 | if not args.nohost and computer.os != "macos":
105 | loops["cycle3"] = (computer.hostappid, cycle3)
106 | loops_indexes[len(loops_indexes)] = "cycle3"
107 | if args.pause_cycle:
108 | loops["pause"] = ("", pause)
109 | loops_indexes[len(loops_indexes)] = "pause"
110 |
111 | run.set_loop(
112 | loops,
113 | loops_indexes,
114 | computer.updateMap,
115 | int(args.poll_rate) if args.poll_rate else 3,
116 | )
117 | run.run_loop(computer)
118 |
119 |
120 | if __name__ == "__main__":
121 | main()
--------------------------------------------------------------------------------
/fetch_cord/args.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 |
3 | import argparse
4 |
5 |
6 | def parse_args():
7 |
8 | parser = argparse.ArgumentParser(
9 | description="Fetch Cord\n" "https://github.com/MrPotatoBobx/FetchCord"
10 | )
11 | parser.add_argument(
12 | "--nodistro", action="store_true", help="Don't show distro info."
13 | )
14 | parser.add_argument(
15 | "--nohardware", action="store_true", help="Don't show hardware info."
16 | )
17 | parser.add_argument(
18 | "--noshell", action="store_true", help="Don't show shell/terminal info."
19 | )
20 | parser.add_argument("--nohost", action="store_true", help="Don't show host info.")
21 | parser.add_argument(
22 | "--noconfig",
23 | action="store_true",
24 | help="Disable neofetch custom config. Enable if you have an incompatible custom configuration.",
25 | )
26 | parser.add_argument(
27 | "--time",
28 | "-t",
29 | metavar="TIME",
30 | action="store",
31 | help="Set custom time in seconds for cycles. Default is 30 seconds",
32 | )
33 | parser.add_argument(
34 | "--terminal",
35 | metavar="TERMINAL",
36 | action="store",
37 | help="Set custom Terminal (useful if using something like dmenu, or launching from a script).",
38 | )
39 | parser.add_argument(
40 | "--termfont",
41 | metavar="TERMFONT",
42 | action="store",
43 | help="Set custom Terminal Font (useful if neofetch can't get it).",
44 | )
45 | parser.add_argument(
46 | "--install",
47 | action="store_true",
48 | help="Install fetchcord as a systemd service (user) and enable it.",
49 | )
50 | parser.add_argument(
51 | "--uninstall",
52 | action="store_true",
53 | help="Uninstall fetchcord as a systemd service (user).",
54 | )
55 | parser.add_argument(
56 | "--enable",
57 | action="store_true",
58 | help="Enable fetchcord systemd service (user).",
59 | )
60 | parser.add_argument(
61 | "--disable",
62 | action="store_true",
63 | help="Disable fetchcord systemd service (user).",
64 | )
65 | parser.add_argument(
66 | "--start",
67 | action="store_true",
68 | help="Start fetchcord systemd service (user).",
69 | )
70 | parser.add_argument(
71 | "--stop",
72 | action="store_true",
73 | help="Stop fetchcord systemd service (user).",
74 | )
75 | parser.add_argument(
76 | "--status",
77 | action="store_true",
78 | help="Get fetchcord systemd service status (user).",
79 | )
80 | parser.add_argument(
81 | "--update",
82 | action="store_true",
83 | help="Update database of distros, hardware, etc.",
84 | )
85 | parser.add_argument(
86 | "--testing",
87 | action="store_true",
88 | help="Get files from testing branch instead of master.",
89 | )
90 | parser.add_argument("--debug", "-d", action="store_true", help="Enable debugging.")
91 | parser.add_argument(
92 | "--pause-cycle",
93 | "-p",
94 | action="store_true",
95 | help="Extra cycle that pauses for 30 seconds or custom time using --time argument.",
96 | )
97 | parser.add_argument(
98 | "--memtype",
99 | "-m",
100 | metavar="TYPE",
101 | action="store",
102 | help="Show Memory in GiB or MiB. Valid vaules are 'gb', 'mb'",
103 | )
104 | parser.add_argument(
105 | "--poll-rate",
106 | "-r",
107 | metavar="RATE",
108 | action="store",
109 | help="Set info polling rate.",
110 | )
111 | parser.add_argument(
112 | "--version", "-v", action="store_true", help="Print FetchCord Version."
113 | )
114 | parser.add_argument(
115 | "--config-path",
116 | "-c",
117 | action="store",
118 | help="Specify custom neofetch config path.",
119 | )
120 | parser.add_argument(
121 | "--fetchcord-config-path",
122 | "-fc",
123 | action="store",
124 | help="Specify custom fetchcord config path.",
125 | )
126 | parser.add_argument(
127 | "--nfco",
128 | "-nfco",
129 | action="store",
130 | help="nfco",
131 | )
132 |
133 | return parser.parse_args()
134 |
--------------------------------------------------------------------------------
/fetch_cord/computer/Computer.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 |
3 | import logging
4 | from sys import platform, exit
5 | import sys
6 | from typing import Callable, Dict, List
7 | import psutil, os
8 |
9 | from ..run_command import exec_bash, run_command
10 | from ..args import parse_args
11 | from ..Logger import Logger
12 | from .flatpak import enableFlatpak
13 | from .resources import get_infos, get_default_config
14 | from .cpu.get_cpu import get_cpu
15 | from .cpu.Cpu_interface import Cpu_interface
16 | from .gpu.get_gpu import get_gpu
17 | from .gpu.Gpu_interface import GpuType, get_gpuid
18 | from .mobo.get_mobo import get_mobo
19 |
20 | args = parse_args()
21 |
22 | # logger = Logger(
23 | # "fetchcord_computer.log",
24 | # "fetchcord_computer",
25 | # logging.DEBUG if args.debug else logging.INFO,
26 | # )
27 |
28 |
29 | class Computer:
30 | parseMap: Dict[str, Callable]
31 | componentMap: Dict[str, List] = {}
32 | idsMap: Dict[str, Dict]
33 |
34 | os: str
35 | neofetchwin: bool = False
36 | neofetch: bool = False
37 | values: str
38 | laptop: bool = False
39 | uptime: float
40 |
41 | @property
42 | def memory(self) -> str:
43 | return self.get_component_line("Memory:")
44 |
45 | @property
46 | def osinfo(self) -> str:
47 | return self.get_component_line("OS:")
48 |
49 | @property
50 | def osinfoid(self) -> str:
51 | component = self.get_component_line("OS:")
52 | component = (component.split()[0] + component.split()[1]).lower()
53 | component_list = self.idsMap[self.idsMap["map"]["OS:"]]
54 |
55 | for comp, id in component_list.items():
56 | if component.lower().find(comp.lower()) >= 0:
57 | return id
58 |
59 | print(
60 | "Unknown {}, contact us on github to resolve this.".format(
61 | self.idsMap["map"]["OS:"]
62 | )
63 | )
64 |
65 | return component_list["unknown"]
66 |
67 | @property
68 | def motherboard(self) -> str:
69 | tmp = self.get_component_line("Motherboard:")
70 | if tmp == "Motherboard: N/A":
71 | return self.host
72 |
73 | return tmp
74 |
75 | @property
76 | def motherboardid(self) -> str:
77 | return self.get_component_idkey("Motherboard:")
78 |
79 | @property
80 | def motherboardappid(self) -> str:
81 | tmp = self.get_component_id("Motherboard:")
82 |
83 | if tmp == self.idsMap[self.idsMap["map"]["Motherboard:"]]["unknown"]:
84 | return self.hostappid
85 |
86 | return tmp
87 |
88 | @property
89 | def host(self) -> str:
90 | return self.get_component_line("Host:")
91 |
92 | @property
93 | def hostid(self) -> str:
94 | hostsplit = self.host.split()
95 | host_list: Dict[str, str] = self.idsMap[self.idsMap["map"]["Host:"]]
96 |
97 | for line in hostsplit:
98 | if line in host_list:
99 | return line
100 |
101 | # try to get MacBook hostid
102 | hostid = []
103 | hostjoin = " ".join(self.host)
104 | for numsplit in range(len(hostjoin)):
105 | if not hostjoin[numsplit].isdigit():
106 | hostid.append(hostjoin[numsplit])
107 | hostid = "".join(hostid)
108 | hostid = hostid.split()[1]
109 |
110 | if hostid in host_list:
111 | return host_list[hostid]
112 | else:
113 | return host_list["unknown"]
114 |
115 | @property
116 | def hostappid(self) -> str:
117 | return self.get_component_id("Host:")
118 |
119 | @property
120 | def cpu(self) -> str:
121 | key = "CPU:"
122 | cpus: List[Cpu_interface] = self.get_component(key)
123 | temp = []
124 | for cpu in cpus:
125 | temp.append(cpu.info)
126 |
127 | return "\n".join(temp) if len(cpus) > 0 else "{} N/A".format(key)
128 |
129 | @property
130 | def cpuid(self) -> str:
131 | temp: List[Cpu_interface] = self.get_component("CPU:")
132 |
133 | if len(temp) == 0:
134 | return self.idsMap[self.idsMap["map"]["CPU:"]]["unknown"]
135 | else:
136 | return temp[0].get_id(self.idsMap[self.idsMap["map"]["CPU:"]])
137 |
138 | @property
139 | def gpu(self) -> str:
140 | key = "GPU:"
141 | gpus: List[GpuType] = self.get_component(key)
142 | temp = []
143 | for gpu in gpus:
144 | if gpu.vendor == "amd" and self.os == "linux":
145 | temp.append(gpu.get_amdgpurender(gpus, self.laptop).rstrip().lstrip())
146 | else:
147 | temp.append(gpu.model.lstrip().rstrip())
148 |
149 | return "\n".join(temp) if len(gpus) > 0 else "{} N/A".format(key)
150 |
151 | @property
152 | def gpuid(self) -> str:
153 | return get_gpuid(
154 | self.idsMap[self.idsMap["map"]["GPU:"]], self.get_component("GPU:")
155 | )
156 |
157 | @property
158 | def disks(self) -> str:
159 | return self.get_component_line("Disk")
160 |
161 | @property
162 | def resolution(self) -> str:
163 | return self.get_component_line("Resolution:")
164 |
165 | @property
166 | def theme(self) -> str:
167 | return self.get_component_line("Theme:")
168 |
169 | @property
170 | def kernel(self) -> str:
171 | return self.get_component_line("Kernel:")
172 |
173 | @property
174 | def packages(self) -> str:
175 | return self.get_component_line("Packages:")
176 |
177 | @property
178 | def shell(self) -> str:
179 | return self.get_component_line("Shell:")
180 |
181 | @property
182 | def shellid(self) -> str:
183 | return self.get_component_id("Shell:")
184 |
185 | @property
186 | def terminal(self) -> str:
187 | return self.get_component_line("Terminal:")
188 |
189 | @property
190 | def terminalid(self) -> str:
191 | return self.get_component_id("Terminal:")
192 |
193 | @property
194 | def wm(self) -> str:
195 | return self.get_component_line("WM:")
196 |
197 | @property
198 | def wmid(self) -> str:
199 | return self.get_component_line("WM:").split()[0]
200 |
201 | @property
202 | def font(self) -> str:
203 | return self.get_component_line("Font:")
204 |
205 | @property
206 | def de(self) -> str:
207 | return self.get_component_line("DE:")
208 |
209 | @property
210 | def deid(self) -> str:
211 | value = self.get_component_line("DE:").split()[0]
212 |
213 | return "n/a" if value == "DE:" else value
214 |
215 | @property
216 | def dewmid(self) -> str:
217 | de = self.get_component_line("DE:")
218 |
219 | return "\n".join(
220 | ["" if de == "{} N/A".format("DE:") else de, self.get_component_line("WM:")]
221 | )
222 |
223 | @property
224 | def desktopid(self) -> str:
225 | deid = self.deid.lower()
226 | wmid = self.wmid.lower()
227 |
228 | if deid == "unity":
229 | if wmid == "compiz":
230 | return "unity"
231 | else:
232 | return wmid
233 |
234 | if deid != "n/a" and deid in self.idsMap[self.idsMap["map"]["DE:"]]:
235 | return deid
236 | elif deid == "n/a" and wmid in self.idsMap[self.idsMap["map"]["WM:"]]:
237 | return wmid
238 | else:
239 | print("Unknown DE/WM, contact us on github to resolve this.")
240 | return "unknown"
241 |
242 | @property
243 | def battery(self) -> str:
244 | if self.laptop:
245 | return self.get_component_line("Battery")
246 | else:
247 | return "{} N/A".format("Battery")
248 |
249 | @property
250 | def lapordesk(self) -> str:
251 | if self.laptop and self.os != "macos":
252 | return "laptop"
253 | else:
254 | return "desktop"
255 |
256 | @property
257 | def version(self) -> str:
258 | return os.popen("sw_vers -productVersion").read()
259 |
260 | @property
261 | def product(self) -> str:
262 | return os.popen("sysctl -n hw.model").read()
263 |
264 | @property
265 | def devicetype(self) -> str:
266 | if self.product[0:7] == "MacBook":
267 | return "laptop"
268 | else:
269 | return "desktop"
270 |
271 | @property
272 | def bigicon(self) -> str:
273 | try:
274 | return self.idsMap[self.idsMap["map"]["Version:"]][self.version[0:5]]
275 | except KeyError:
276 | print("Unsupported MacOS version")
277 | return "bigslurp"
278 |
279 | def __init__(self):
280 | super().__init__()
281 |
282 | self.parseMap = {
283 | "CPU:": get_cpu,
284 | "GPU:": get_gpu,
285 | "Disk": self.get_disk,
286 | "Memory:": self.get_memory,
287 | "OS:": self.get,
288 | "Motherboard:": get_mobo,
289 | "Host:": self.get,
290 | "Resolution:": self.get,
291 | "Theme:": self.get,
292 | "Kernel:": self.get,
293 | "Packages:": self.get,
294 | "Shell:": self.get,
295 | "Terminal:": self.get,
296 | "Font:": self.get,
297 | "DE:": self.get,
298 | "WM:": self.get,
299 | "Battery": self.get_battery,
300 | }
301 |
302 | self.idsMap = get_infos()
303 | self.uptime = psutil.boot_time()
304 |
305 | self.detect_os()
306 | self.detect_laptop()
307 |
308 | self.fetch_values()
309 |
310 | def fetch_values(self):
311 | self.neofetchwin, self.neofetch, self.values = self.detect_neofetch()
312 |
313 | self.neofetch_parser(self.values)
314 |
315 | if not bool(self.componentMap):
316 | args.config_path = ""
317 | args.noconfig = False
318 |
319 | self.neofetchwin, self.neofetch, self.values = self.detect_neofetch()
320 | self.neofetch_parser(self.values)
321 |
322 | terminallist = self.idsMap[self.idsMap["map"]["Terminal:"]]
323 | if args.terminal and args.terminal.lower() in terminallist:
324 | self.componentMap["Terminal:"] = [args.terminal.lower()]
325 | elif args.terminal and args.terminal.lower() not in terminallist:
326 | print(
327 | "\nInvalid terminal, only %s are supported.\n"
328 | "Please make a github issue if you would like to have your terminal added.\n"
329 | "https://github.com/MrPotatoBobx/FetchCord" % terminallist
330 | )
331 | sys.exit(1)
332 |
333 | if self.get_component("Font:", True) and args.termfont:
334 | print(
335 | "Custom terminal font not set because a terminal font already exists, %s"
336 | % self.font
337 | )
338 | elif not self.get_component("Font:", True) and args.termfont:
339 | self.componentMap["Font:"] = [args.termfont]
340 |
341 | def updateMap(self):
342 | """
343 | Clear the components values and fetch new ones
344 | """
345 | self.clearMap()
346 | self.neofetchwin, self.neofetch, self.values = self.detect_neofetch()
347 | self.neofetch_parser(self.values)
348 |
349 | def clearMap(self):
350 | """
351 | Clear the components values
352 | """
353 | for key in self.componentMap.keys():
354 | del self.componentMap[key][:]
355 |
356 | def neofetch_parser(self, values: str):
357 | if args.debug:
358 | print(values)
359 | lines = values.split("\n")
360 | for i in range(len(lines)):
361 | line = lines[i]
362 | for key, detectedFunction in [
363 | (key, value) for key, value in self.parseMap.items() if key in line
364 | ]:
365 | if key not in self.componentMap:
366 | self.componentMap[key] = []
367 | detectedFunction(
368 | self.os, self.componentMap[key], line.rstrip("\n"), key
369 | )
370 |
371 | def detect_os(self) -> str:
372 | if platform == "linux" or platform == "linux2":
373 | self.os = "linux"
374 | elif platform == "darwin":
375 | self.os = "macos"
376 | elif platform == "win32":
377 | self.os = "windows"
378 | else:
379 | raise Exception("Not a supported OS !")
380 |
381 | return self.os
382 |
383 | def detect_laptop(self) -> bool:
384 | if self.os != "linux":
385 | self.laptop = False
386 | else:
387 | for i in os.listdir("/sys/class/power_supply"):
388 | if i.startswith("BAT"):
389 | self.laptop = True
390 | break
391 |
392 | return self.laptop
393 |
394 | def detect_neofetch(self):
395 | neofetchwin = False
396 | neofetch = False
397 | values = None
398 |
399 | if self.os == "windows":
400 | try:
401 | values = run_command(["neofetch", "--noart"])
402 | if args.nfco:
403 | with open(args.nfco) as f:
404 | values = "\n".join(f.readlines())
405 |
406 | except Exception:
407 | pass
408 | else:
409 | neofetchwin = True
410 | if not neofetchwin:
411 | if self.os == "linux":
412 | enableFlatpak()
413 |
414 | default_config = get_default_config()
415 |
416 | try:
417 | if self.os == "windows":
418 | values = run_command(
419 | [
420 | "neofetch",
421 | "--config {}".format(
422 | "none"
423 | if args.noconfig
424 | else (
425 | args.config_path
426 | if args.config_path
427 | else (default_config)
428 | )
429 | ),
430 | "--stdout",
431 | ],
432 | shell=(self.os == "windows"),
433 | )
434 | else:
435 | values = exec_bash(
436 | "neofetch --config {} --stdout".format(
437 | "none"
438 | if args.noconfig
439 | else (
440 | args.config_path
441 | if args.config_path
442 | else (default_config)
443 | )
444 | )
445 | )
446 | if args.nfco:
447 | with open(args.nfco) as f:
448 | values = "\n".join(f.readlines())
449 |
450 | except Exception:
451 | print(
452 | "ERROR: Neofetch not found, please install it or check installation and that neofetch is in PATH."
453 | )
454 | exit(1)
455 | else:
456 | neofetch = True
457 |
458 | return (neofetchwin, neofetch, values)
459 |
460 | def get_battery(self, os: str, line: List, value: str, key: str):
461 | """
462 | Append the Battery info from given neofetch line
463 |
464 | Parameters
465 | ----------
466 | value : str
467 | Neofetch extracted line
468 | """
469 |
470 | line.append(value[value.find(key) + len(key) + 2 :])
471 |
472 | def get_disk(self, os: str, line: List, value: str, key: str):
473 | """
474 | Append the Disk info from the given neofetch line to the Disk list
475 |
476 | Parameters
477 | ----------
478 | value : str
479 | Neofetch extracted line
480 | """
481 |
482 | line.append(value[value.find(key) + len(key) + 2 :])
483 |
484 | def get_memory(self, os: str, line: List, value: str, key: str):
485 | """
486 | Get the memory info from the given neofetch line
487 |
488 | Parameters
489 | ----------
490 | value : str
491 | Neofetch extracted line
492 | """
493 |
494 | if args.memtype == "gb":
495 | memgb = value.split()
496 | used = float(memgb[1].replace("MiB", ""))
497 | total = float(memgb[3].replace("MiB", ""))
498 |
499 | line.append(
500 | " ".join(
501 | [
502 | str(round(used / 1024, 2)),
503 | "GiB /",
504 | str(round(total / 1024, 2)),
505 | "GiB",
506 | ]
507 | )
508 | )
509 | else:
510 | line.append(value[value.find(key) + len(key) + 1 :])
511 |
512 | def get(self, os: str, line: List, value: str, key: str, valueOffset: int = 1):
513 | """
514 | Get the info from the given neofetch line
515 |
516 | Parameters
517 | ----------
518 | os: str
519 | Detected OS ("windows", "linux" or "macos")
520 | line: List
521 | List who will contains the values
522 | value : str
523 | Neofetch extracted line
524 | key : str
525 | Key for the dict
526 | valueOffset: int
527 | Offset for extracting the value without the key (default : 1)
528 | """
529 |
530 | line.append(value[value.find(key) + len(key) + valueOffset :])
531 |
532 | def get_component(self, key: str, quiet: bool = False):
533 | """
534 | Get component info from map
535 |
536 | Args:
537 | key (str): component key in map
538 | """
539 | try:
540 | return self.componentMap[key]
541 | except KeyError as err:
542 | if args.debug:
543 | print("[KeyError]: {}".format(err), end="")
544 |
545 | return []
546 |
547 | def get_component_line(self, key: str) -> str:
548 | try:
549 | values = self.componentMap[key]
550 | return "\n".join(values) if len(values) > 0 else "{} N/A".format(key)
551 | except KeyError as err:
552 | if args.debug:
553 | print("[KeyError]: ", end="")
554 | print(err)
555 |
556 | return "{} N/A".format(key)
557 |
558 | def get_component_id(self, key: str) -> str:
559 | component = self.get_component_line(key).lower()
560 | component_list = self.idsMap[self.idsMap["map"][key]]
561 |
562 | for comp, id in component_list.items():
563 | if component.find(comp.lower()) >= 0:
564 | return id
565 |
566 | print(
567 | "Unknown {}, contact us on github to resolve this.".format(
568 | self.idsMap["map"][key]
569 | )
570 | )
571 | if args.debug:
572 | print(f"Value: {component}")
573 |
574 | return component_list["unknown"]
575 |
576 | def get_component_idkey(self, key: str) -> str:
577 | component = self.get_component_line(key).lower()
578 | component_list = self.idsMap[self.idsMap["map"][key]]
579 |
580 | for comp, _ in component_list.items():
581 | if component.find(comp.lower()) >= 0:
582 | return comp
583 |
584 | print(
585 | "Unknown {}, contact us on github to resolve this.".format(
586 | self.idsMap["map"][key]
587 | )
588 | )
589 |
590 | return component_list["unknown"]
591 |
--------------------------------------------------------------------------------
/fetch_cord/computer/Peripheral_interface.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 | from abc import ABCMeta
4 |
5 |
6 | class Peripherical_interface(metaclass=ABCMeta):
7 | os: str
8 |
9 | def __init__(self, os):
10 | super().__init__()
11 | self.os = os
--------------------------------------------------------------------------------
/fetch_cord/computer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/fetch_cord/computer/__init__.py
--------------------------------------------------------------------------------
/fetch_cord/computer/cpu/Cpu_amd.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 |
3 | import os
4 | from sys import platform
5 |
6 | if os.name != "nt" and platform != "darwin":
7 | from psutil import sensors_temperatures
8 | from .Cpu_interface import Cpu_interface
9 |
10 | CPU_VENDOR = "amd"
11 |
12 |
13 | class Cpu_amd(Cpu_interface):
14 | def __init__(self, os, model):
15 | super().__init__(os, CPU_VENDOR, model)
16 |
17 | @Cpu_interface.model.setter
18 | def model(self, value: str):
19 | self.info = " ".join(value.split()[1:])
20 | self._model = " ".join([value.split()[2], value.split()[3]])
21 |
22 | if self._model.find("APU") != -1 or (
23 | self._model.find("RADEON") != -1 and self._model.lower().find("ryzen") == -1
24 | ):
25 | self._model = f"{self._model.split('-')[0]} APU"
26 |
27 | def get_temp(self) -> float:
28 | if self.os == "windows":
29 | raise NotImplementedError(
30 | "Temperature report for AMD CPU's is not supported on Windows yet."
31 | )
32 | elif self.os == "macos":
33 | raise NotImplementedError(
34 | "Temperature report for AMD CPU's is not supported on MacOS yet."
35 | )
36 | elif (
37 | self.os == "linux" # and os.name != "nt" linux only
38 | ): # os.name comparaison not needed, its just for the linter
39 | sensors = sensors_temperatures()
40 | if "k10temp" in sensors:
41 | temps = sensors["k10temp"]
42 | if len(temps) == 1:
43 | return temps.current
44 | else:
45 | for temp in temps:
46 | if temp.label == "Tdie":
47 | return temp.current
48 |
49 | raise Exception("No valid temperature value found.")
50 |
51 | raise Exception("No valid sensor found.")
52 | else:
53 | raise NotImplementedError("Unknown OS, no CPU temperature report.")
54 |
--------------------------------------------------------------------------------
/fetch_cord/computer/cpu/Cpu_intel.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 | from .Cpu_interface import Cpu_interface
4 | import re
5 |
6 | CPU_VENDOR = "intel"
7 |
8 |
9 | class Cpu_intel(Cpu_interface):
10 | def __init__(self, os, model):
11 | super().__init__(os, CPU_VENDOR, model)
12 |
13 | @Cpu_interface.model.setter
14 | def model(self, value: str):
15 | self.info = " ".join(value.split()[1:])
16 | if value.split()[1].replace("Intel(R)", "Intel") == "Pentium":
17 | self._model = value.split()[1]
18 | else:
19 | # Remove "CPU: ", "(R)" and "(TM)"
20 | self._model = " ".join(
21 | re.sub(r"\((.+)\)", "", value.replace("-", " ")).split()[1:]
22 | )
23 |
24 | # Core 2 Duo, Core 2 Quad
25 | if self._model.find("Intel Core") != -1:
26 | self._model = " ".join(self._model.split()[:4])
27 | else:
28 | self._model = " ".join(self._model.split()[:2])
29 |
30 | if self._model == "Intel Core":
31 | self._model = value.split()[1:5]
32 | self._model = " ".join(self._model)
33 |
34 | def get_temp(self):
35 | if self.os == "windows":
36 | raise NotImplementedError(
37 | "Temperature report for Intel CPU's is not supported on Windows yet."
38 | )
39 | elif self.os == "macos":
40 | raise NotImplementedError(
41 | "Temperature report for Intel CPU's is not supported on MacOS yet."
42 | )
43 | elif self.os == "linux":
44 | raise NotImplementedError(
45 | "Temperature report for Intel CPU's is not supported on Linux yet."
46 | )
47 | else:
48 | raise NotImplementedError("Unkown OS, no CPU temperature report.")
49 |
--------------------------------------------------------------------------------
/fetch_cord/computer/cpu/Cpu_interface.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 | from abc import ABCMeta, abstractmethod
4 | from typing import Dict
5 |
6 | from ..Peripheral_interface import Peripherical_interface
7 |
8 |
9 | class Cpu_interface(Peripherical_interface, metaclass=ABCMeta):
10 | vendor: str
11 | _model: str
12 | info: str
13 |
14 | @property
15 | def model(self) -> str:
16 | return self._model
17 |
18 | @model.setter
19 | @abstractmethod
20 | def model(self, value: str):
21 | raise NotImplementedError
22 |
23 | @property
24 | def temp(self) -> float:
25 | try:
26 | self._temp = self.get_temp()
27 | except NotImplementedError as e:
28 | try:
29 | raise e
30 | finally:
31 | e = None
32 | del e
33 |
34 | else:
35 | return self._temp
36 |
37 | @temp.setter
38 | def temp(self, value: float):
39 | self._temp = value
40 |
41 | def __init__(self, os, vendor, model):
42 | super().__init__(os)
43 | self.vendor = vendor
44 | self.model = model
45 |
46 | @abstractmethod
47 | def get_temp(self) -> float:
48 | raise NotImplementedError
49 |
50 | def get_id(self, cpu_list: Dict[str, str]) -> str:
51 | if self.model.lower() in cpu_list[self.vendor]:
52 | return cpu_list[self.vendor][self.model.lower()]
53 | else:
54 | return cpu_list["unknown"]
55 |
--------------------------------------------------------------------------------
/fetch_cord/computer/cpu/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/fetch_cord/computer/cpu/__init__.py
--------------------------------------------------------------------------------
/fetch_cord/computer/cpu/get_cpu.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 | from typing import List
4 |
5 | from .Cpu_amd import Cpu_amd
6 | from .Cpu_intel import Cpu_intel
7 |
8 |
9 | def get_cpu(os: str, line: List, value: str, key: str):
10 | """
11 | Append the CPU info from the given neofetch line to the CPU list
12 |
13 | Parameters
14 | ----------
15 | os :
16 | OS type
17 | line : List
18 | Component line
19 | value : str
20 | Neofetch extracted line
21 | key : str
22 | Component key
23 | """
24 |
25 | vendor = value.replace(key, "").lstrip("").replace("Intel(R)", "Intel")
26 |
27 | if vendor.find("Intel") != -1 or vendor.find("Pentium") != -1:
28 | line.append(Cpu_intel(os, value))
29 | elif vendor.find("AMD") != -1:
30 | line.append(Cpu_amd(os, value))
--------------------------------------------------------------------------------
/fetch_cord/computer/flatpak.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 | from fetch_cord.run_command import BashError, exec_bash
4 | import os
5 |
6 |
7 | def enableFlatpak():
8 | home = os.getenv("HOME")
9 | flatpak_discord_path = os.path.isdir("%s/.var/app/com.discordapp.Discord" % home)
10 | package_path = os.path.isfile("/usr/bin/discord")
11 | manual_install_path = os.path.isdir("/opt/Discord")
12 | if flatpak_discord_path and not package_path and not manual_install_path:
13 | XDG_Symlink(home)
14 |
15 |
16 | def XDG_Symlink(home):
17 | try:
18 | print("Symlinking XDG_RUNTIME_DIR path for Flatpak Discord.")
19 | exec_bash(
20 | "cd %s/.var && ln -sf {app/com.discordapp.Discord,$XDG_RUNTIME_DIR}/discord-ipc-0 "
21 | % home
22 | )
23 | except BashError as e:
24 | print("Could not symlink XDG_RUNTIME_DIR Error: %s" % str(e))
25 | return
26 |
--------------------------------------------------------------------------------
/fetch_cord/computer/gpu/Gpu_amd.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 | from fetch_cord.run_command import BashError, exec_bash
3 | from typing import List
4 | import sys
5 |
6 | from .Gpu_interface import Gpu_interface, GpuType
7 |
8 | GPU_VENDOR = "amd"
9 |
10 |
11 | class Gpu_amd(Gpu_interface):
12 | def __init__(self, os, model):
13 | super().__init__(os, GPU_VENDOR, model)
14 |
15 | @Gpu_interface.model.setter
16 | def model(self, value: str):
17 | self._model = value
18 |
19 | def get_temp(self):
20 | if self.os == "windows":
21 | raise NotImplementedError(
22 | "Temperature report for AMD GPU's is not supported on Windows yet."
23 | )
24 | elif self.os == "macos":
25 | raise NotImplementedError(
26 | "Temperature report for AMD GPU's is not supported on MacOS yet."
27 | )
28 | elif self.os == "linux":
29 | raise NotImplementedError(
30 | "Temperature report for AMD GPU's is not supported on Linux yet."
31 | )
32 | else:
33 | raise NotImplementedError("Unknown OS, no GPU temperature report.")
34 |
35 | def get_amdgpurender(self, gpu_list: List[GpuType], laptop: bool) -> str:
36 | try:
37 | for i in range(len(gpu_list)):
38 | # assume DRI_PRIME=0 is the intel GPU
39 | if laptop and "intel" == gpu_list[i].vendor.lower():
40 | i += 1
41 | if (
42 | laptop
43 | and "amd" == gpu_list[i].vendor.lower()
44 | and gpu_list[i].model != self.model
45 | ):
46 | i += 1
47 |
48 | env_prime = "DRI_PRIME=%s" % i
49 | return exec_bash(
50 | "%s glxinfo | grep \"OpenGL renderer string:\" |sed 's/^.*: //;s/[(][^)]*[)]//g'"
51 | % env_prime
52 | )
53 | except BashError as e:
54 | print("ERROR: Could not run glxinfo [%s]" % str(e))
55 | sys.exit(1)
--------------------------------------------------------------------------------
/fetch_cord/computer/gpu/Gpu_intel.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 | from .Gpu_interface import Gpu_interface
3 |
4 | GPU_VENDOR = "intel"
5 |
6 |
7 | class Gpu_intel(Gpu_interface):
8 | def __init__(self, os, model):
9 | super().__init__(os, GPU_VENDOR, model)
10 |
11 | @Gpu_interface.model.setter
12 | def model(self, value: str):
13 | self._model = value
14 |
15 | @Gpu_interface.vendor.setter
16 | def vendor(self, value: str):
17 | self._vendor = value.replace(f"{GPU_VENDOR}(R)", f"{GPU_VENDOR}")
18 |
19 |
20 | def get_temp(self):
21 | if self.os == "windows":
22 | raise NotImplementedError(
23 | "Temperature report for Intel GPU's is not supported on Windows yet."
24 | )
25 | elif self.os == "macos":
26 | raise NotImplementedError(
27 | "Temperature report for Intel GPU's is not supported on MacOS yet."
28 | )
29 | elif self.os == "linux":
30 | raise NotImplementedError(
31 | "Temperature report for Intel GPU's is not supported on Linux yet."
32 | )
33 | else:
34 | raise NotImplementedError("Unknown OS, no GPU temperature report.")
35 |
--------------------------------------------------------------------------------
/fetch_cord/computer/gpu/Gpu_interface.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 | from abc import ABCMeta, abstractmethod
3 | from typing import List, TypeVar, Dict
4 |
5 | from ..Peripheral_interface import Peripherical_interface
6 |
7 |
8 | class Gpu_interface(Peripherical_interface, metaclass=ABCMeta):
9 | _vendor: str
10 | _model: str
11 |
12 | @property
13 | def vendor(self) -> str:
14 | return self._vendor
15 |
16 | @vendor.setter
17 | def vendor(self, value: str):
18 | self._vendor = value
19 |
20 | @property
21 | def model(self) -> str:
22 | return self._model
23 |
24 | @model.setter
25 | @abstractmethod
26 | def model(self, value: str):
27 | raise NotImplementedError
28 |
29 | @property
30 | def temp(self) -> float:
31 | try:
32 | self._temp = self.get_temp()
33 | except NotImplementedError as e:
34 | try:
35 | raise e
36 | finally:
37 | e = None
38 | del e
39 |
40 | else:
41 | return self._temp
42 |
43 | @temp.setter
44 | def temp(self, value: float):
45 | self._temp = value
46 |
47 | def __init__(self, os, vendor, model):
48 | super().__init__(os)
49 | self.vendor = vendor
50 | self.model = model
51 |
52 | @abstractmethod
53 | def get_temp(self) -> float:
54 | raise NotImplementedError
55 |
56 |
57 | GpuType = TypeVar("GpuType", bound="Gpu_interface")
58 |
59 |
60 | def get_gpuid(gpu_ids: Dict[str, str], gpus: List[GpuType]):
61 | vendors = []
62 | for i in range(len(gpus)):
63 | if gpus[i].vendor not in vendors:
64 | vendors.append(gpus[i].vendor)
65 |
66 | gpuvendor = "".join(vendors).lower()
67 |
68 | if gpuvendor in gpu_ids:
69 | return gpu_ids[gpuvendor]
70 | else:
71 | print("Unknown GPU, contact us on github to resolve this.")
72 | return "unknown"
73 |
--------------------------------------------------------------------------------
/fetch_cord/computer/gpu/Gpu_nvidia.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 | from fetch_cord.run_command import BashError, exec_bash
3 | from .Gpu_interface import Gpu_interface
4 |
5 | GPU_VENDOR = "nvidia"
6 |
7 |
8 | class Gpu_nvidia(Gpu_interface):
9 | primeoffload: bool
10 |
11 | def __init__(self, os, model):
12 | super().__init__(os, GPU_VENDOR, model)
13 |
14 | @Gpu_interface.model.setter
15 | def model(self, value: str):
16 | self._model = value
17 |
18 | def get_temp(self):
19 | if self.os == "windows":
20 | raise NotImplementedError(
21 | "Temperature report for Nvidia GPU's is not supported on Windows yet."
22 | )
23 | elif self.os == "macos":
24 | raise NotImplementedError(
25 | "Temperature report for Nvidia GPU's is not supported on MacOS yet."
26 | )
27 | elif self.os == "linux":
28 | try:
29 | return exec_bash(
30 | "nvidia-smi -q | awk '/GPU Current Temp/{print $5}' | sed 's/^/[/;s/$/°C]/'"
31 | )
32 | except BashError:
33 | pass
34 | else:
35 | raise NotImplementedError("Unknown OS, no GPU temperature report.")
36 |
37 | def check_primeoffload(self):
38 | # only show the GPU in use with optimus, show both if prime render offload
39 | self.primeoffload = False
40 | try:
41 | self.primeoffload = exec_bash('xrandr --listproviders | grep -o "NVIDIA-0"')
42 | return True
43 | except BashError:
44 | return False
--------------------------------------------------------------------------------
/fetch_cord/computer/gpu/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/fetch_cord/computer/gpu/__init__.py
--------------------------------------------------------------------------------
/fetch_cord/computer/gpu/get_gpu.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 | from typing import List
3 |
4 | from .Gpu_amd import Gpu_amd
5 | from .Gpu_nvidia import Gpu_nvidia
6 | from .Gpu_intel import Gpu_intel
7 |
8 |
9 | def get_gpu(os: str, line: List, value: str, key: str):
10 | """
11 | Append the GPU info from the given neofetch line to the GPU list
12 |
13 | Parameters
14 | ----------
15 | os :
16 | OS type
17 | line : List
18 | Component line
19 | value : str
20 | Neofetch extracted line
21 | key : str
22 | Component key
23 | """
24 |
25 | value = value.replace(key, "").lstrip()
26 | splitValue = value.split()
27 |
28 | for v in splitValue:
29 | if v.upper() in ["AMD", "RADEON"]:
30 | line.append(Gpu_amd(os, value))
31 | return
32 | elif v.upper() in ["NVIDIA", "GEFORCE"]:
33 | line.append(Gpu_nvidia(os, value))
34 | return
35 | elif v.upper() in ["INTEL", "INTEL(R)"]:
36 | line.append(Gpu_intel(os, value))
37 | return
--------------------------------------------------------------------------------
/fetch_cord/computer/mobo/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/fetch_cord/computer/mobo/__init__.py
--------------------------------------------------------------------------------
/fetch_cord/computer/mobo/get_mobo.py:
--------------------------------------------------------------------------------
1 | from fetch_cord.run_command import exec_bash
2 | from typing import List
3 |
4 |
5 | def get_mobo(os: str, line: List, value: str, key: str):
6 | if(os == "linux"):
7 | line.append(exec_bash("cat /sys/devices/virtual/dmi/id/board_vendor"))
8 | else:
9 | line.append(value[value.find(key) + len(key) + 1 :])
--------------------------------------------------------------------------------
/fetch_cord/computer/resources.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 |
4 | try:
5 | import importlib.resources as pkg_resources
6 | except ImportError:
7 | # Try backported to PY<37 `importlib_resources`.
8 | import importlib_resources as pkg_resources
9 | import json
10 |
11 | from .. import resources as fc_resources
12 |
13 |
14 | def get_infos():
15 | with pkg_resources.open_text(fc_resources, "fetchcord_ids.json") as f:
16 | infos = json.load(f)
17 |
18 | return infos
19 |
20 |
21 | def get_default_config():
22 | with pkg_resources.path(fc_resources, "default.conf") as path:
23 | return path
24 |
25 | return None
26 |
--------------------------------------------------------------------------------
/fetch_cord/config.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 |
4 | try:
5 | import importlib.resources as pkg_resources
6 | except ImportError:
7 | # Try backported to PY<37 `importlib_resources`.
8 | import importlib_resources as pkg_resources
9 | import os, copy, json, configparser
10 |
11 | from . import resources as fc_resources
12 | from .args import parse_args
13 |
14 |
15 | args = parse_args()
16 |
17 |
18 | class ConfigError(Exception):
19 | pass
20 |
21 |
22 | def load_config():
23 | default_config = configparser.ConfigParser()
24 | with pkg_resources.path(fc_resources, "fetch_cord.conf") as path:
25 | default_config.read_file(open(path))
26 | default_config.read(
27 | ["/etc/fetch_cord.conf", os.path.expanduser("~/fetch_cord.conf")]
28 | )
29 | if args.fetchcord_config_path != None:
30 | default_config.read([args.fetchcord_config_path])
31 | for item in default_config.items():
32 | print(item)
33 |
34 | default_config = _parsed_config_to_dict(default_config)
35 | _validate_config(default_config)
36 |
37 | return default_config
38 |
39 |
40 | # def load_config():
41 | # base_config = configparser.ConfigParser()
42 | # base_config.read(["/etc/fetch_cord.conf"])
43 | # base_config = _parsed_config_to_dict(base_config)
44 | # _validate_config(base_config)
45 |
46 |
47 | # # try:
48 | # user_config = configparser.ConfigParser()
49 | # user_config.read("/etc/fetch_cord.conf")
50 | # user_config = _parsed_config_to_dict(user_config)
51 | # # except configparser.ParsingError as e:
52 | # # print(
53 | # # "Error parsing config file %s. Falling back to default config %s. Error is : %s",
54 | # # envs.USER_CONFIG_COPY_PATH, envs.DEFAULT_CONFIG_PATH, str(e))
55 | # return base_config
56 |
57 | # corrected_config = _validate_config(user_config, fallback_config=base_config)
58 |
59 |
60 | # return corrected_config
61 |
62 |
63 | def _validate_config(config, fallback_config=None):
64 |
65 | folder_path = os.path.dirname(os.path.abspath(__file__))
66 | schema_path = os.path.join(folder_path, "config_schema.json")
67 |
68 | with open(schema_path, "r") as f:
69 | schema = json.load(f)
70 |
71 | corrected_config = copy.deepcopy(config)
72 |
73 | # Checking if the config file has the required sections and options
74 | for section in schema.keys():
75 |
76 | if section not in config.keys():
77 | raise ConfigError("Cannot find header for section [%s]" % section)
78 |
79 | for option in schema[section].keys():
80 |
81 | if option not in config[section].keys():
82 | raise ConfigError(
83 | 'Cannot find option "%s" in section [%s]' % (option, section)
84 | )
85 |
86 | valid, msg = _validate_option(
87 | schema[section][option], config[section][option]
88 | )
89 |
90 | if not valid:
91 | error_msg = (
92 | 'Config parsing : error in option "%s" in section [%s] : %s'
93 | % (option, section, msg)
94 | )
95 | if fallback_config is not None:
96 | print(error_msg)
97 | print(
98 | 'Falling back to default value "%s"',
99 | fallback_config[section][option],
100 | )
101 | corrected_config[section][option] = fallback_config[section][option]
102 |
103 | else:
104 | raise ConfigError(error_msg)
105 |
106 | # Checking if the config file has no unknown section or option
107 | for section in config.keys():
108 |
109 | if section not in schema.keys():
110 | print("Config parsing : unknown section [%s]. Ignoring.", section)
111 | continue
112 |
113 | for option in config[section].keys():
114 | if option not in schema[section].keys():
115 | print(
116 | 'Config parsing : unknown option "%s" in section [%s]. Ignoring.',
117 | option,
118 | section,
119 | )
120 | del corrected_config[section][option]
121 |
122 | return corrected_config
123 |
124 |
125 | def _parsed_config_to_dict(config):
126 |
127 | config_dict = {}
128 |
129 | for section in config.keys():
130 |
131 | if section == "DEFAULT":
132 | continue
133 |
134 | config_dict[section] = {}
135 |
136 | for option in config[section].keys():
137 | config_dict[section][option] = config[section][option]
138 |
139 | return config_dict
140 |
141 |
142 | def _validate_option(schema_option_info, config_option_value):
143 | valid = False
144 | msg = "error"
145 |
146 | parameter_type = schema_option_info[0]
147 |
148 | assert parameter_type in ["multi_words", "single_word", "integer"]
149 |
150 | # Multiple-words parameters
151 | if parameter_type == "multi_words":
152 | valid, msg = _validate_multi_words(schema_option_info, config_option_value)
153 |
154 | # Single-word parameters
155 | elif parameter_type == "single_word":
156 | valid, msg = _validate_single_word(schema_option_info, config_option_value)
157 |
158 | # Integer parameter
159 | elif parameter_type == "integer":
160 | valid, msg = _validate_integer(schema_option_info, config_option_value)
161 |
162 | return valid, msg
163 |
164 |
165 | def _validate_multi_words(schema_option_info, config_option_value):
166 |
167 | parameter_type, allowed_values, can_be_blank = schema_option_info
168 | assert parameter_type == "multi_words"
169 |
170 | values = config_option_value.replace(" ", "").split(",")
171 |
172 | if values == [""]:
173 | if not can_be_blank:
174 | msg = "at least one parameter required"
175 | return False, msg
176 |
177 | else:
178 | for val in values:
179 | if val not in allowed_values:
180 | msg = 'invalid value "%s"' % val
181 | return False, msg
182 |
183 | return True, None
184 |
185 |
186 | def _validate_single_word(schema_option_info, config_option_value):
187 |
188 | parameter_type, allowed_values, can_be_blank = schema_option_info
189 | assert parameter_type == "single_word"
190 |
191 | val = config_option_value.replace(" ", "")
192 |
193 | if val == "":
194 | if not can_be_blank:
195 | msg = "non-blank value required"
196 | return False, msg
197 |
198 | else:
199 | if val not in allowed_values:
200 | msg = 'invalid value "%s"' % val
201 | return False, msg
202 |
203 | return True, None
204 |
205 |
206 | def _validate_integer(schema_option_info, config_option_value):
207 |
208 | parameter_type, can_be_blank = schema_option_info
209 | assert parameter_type == "integer"
210 |
211 | val = config_option_value.replace(" ", "")
212 |
213 | if val == "":
214 | if not can_be_blank:
215 | msg = "non-blank integer value required"
216 | return False, msg
217 |
218 | else:
219 | try:
220 | v = int(val)
221 | if v <= 0:
222 | raise ValueError
223 | except ValueError:
224 | msg = "non-blank integer value required"
225 | return False, msg
226 |
227 | return True, None
228 |
--------------------------------------------------------------------------------
/fetch_cord/config_schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "cycle_0":
3 | {
4 | "top_line": ["single_word", ["kernel", "packages"], false],
5 | "bottom_line": ["single_word", ["kernel", "packages"], false],
6 | "de_wm_icon": ["single_word", ["on", "off"], true],
7 | "time": ["single_word", ["15", "30", "45", "60", "75", "90", "105", "120", "240", "480"], false]
8 | },
9 |
10 | "cycle_1":
11 | {
12 | "top_line": ["single_word", ["cpu", "gpu", "mem", "disk"], false],
13 | "bottom_line": ["single_word", ["cpu", "gpu", "mem", "disk"], false],
14 | "gpu_icon": ["single_word", ["on", "off"], true],
15 | "time": ["single_word", ["15", "30", "45", "60", "75", "90", "105", "120", "240", "480"], false]
16 | },
17 |
18 | "cycle_2":
19 | {
20 | "top_line": ["single_word", ["font", "shell", "theme"], false],
21 | "bottom_line": ["single_word", ["font", "shell", "theme"], false],
22 | "shell_icon": ["single_word", ["on", "off"], true],
23 | "time": ["single_word", ["15", "30", "45", "60", "75", "90", "105", "120", "240", "480"], false]
24 | },
25 |
26 | "cycle_3":
27 | {
28 | "top_line": ["single_word", ["resolution", "battery", "host"], false],
29 | "bottom_line": ["single_word", ["resolution", "battery", "host"], false],
30 | "lapordesk_icon": ["single_word", ["on", "off"], true],
31 | "time": ["single_word", ["15", "30", "45", "60", "75", "90", "105", "120", "240", "480"], false]
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/fetch_cord/cycles.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 | import time
4 | from typing import Dict
5 |
6 | from .computer.Computer import Computer
7 | from .run_rpc import Run_rpc
8 | from .args import parse_args
9 |
10 | args = parse_args()
11 |
12 |
13 | class Cycles:
14 | config: Dict[str, str]
15 |
16 | def __init__(self, config: Dict[str, str]):
17 | self.config = config
18 |
19 |
20 | def pause(run: Run_rpc, key: str, computer: Computer):
21 | if args.debug:
22 | print("pause_cycle")
23 | if args.time:
24 | time.sleep(int(args.time))
25 | else:
26 | time.sleep(30)
27 |
28 |
29 | def windows(run: Run_rpc, key: str, computer: Computer):
30 | if args.debug:
31 | print("w_cycle 0")
32 |
33 | run.try_update(
34 | key,
35 | state=computer.osinfo,
36 | details=computer.memory,
37 | large_image="big",
38 | large_text=computer.osinfo,
39 | small_image=computer.motherboardid,
40 | small_text=computer.motherboard,
41 | start=computer.uptime,
42 | )
43 |
44 | if args.time:
45 | time.sleep(int(args.time))
46 | elif args.nohardware:
47 | time.sleep(9999)
48 | else:
49 | time.sleep(30)
50 | run.try_clear(key)
51 |
52 |
53 | def runmac(run: Run_rpc, key: str, computer: Computer):
54 | if args.debug:
55 | print("runmac")
56 | print("devicetype: %s" % computer.devicetype)
57 | print("product %s" % computer.product)
58 | print("bigicon: %s" % computer.bigicon)
59 | print("ver: %s" % computer.version)
60 | print("uptime: %s" % computer.uptime)
61 |
62 | run.try_update(
63 | key,
64 | state=computer.packages, # update state as packages
65 | details=computer.kernel, # update details as kernel
66 | large_image=computer.bigicon, # set icon
67 | large_text=computer.osinfo, # set large icon text
68 | small_image=computer.devicetype, # set small image icon
69 | small_text=computer.product, # set small image text
70 | start=computer.uptime,
71 | )
72 | if args.time:
73 | time.sleep(int(args.time))
74 | elif args.nohost and args.nohardware and args.noshell:
75 | time.sleep(9999)
76 | else:
77 | time.sleep(30)
78 | run.try_clear(key)
79 |
80 |
81 | def cycle0(run: Run_rpc, key: str, computer: Computer):
82 | top_line = run.config["cycle_0"]["top_line"]
83 | if top_line == "kernel":
84 | top_line = computer.kernel
85 | else:
86 | top_line = computer.packages
87 | bottom_line = run.config["cycle_0"]["bottom_line"]
88 | if bottom_line == "kernel":
89 | bottom_line = computer.kernel
90 | else:
91 | bottom_line = computer.packages
92 | de_wm_icon = run.config["cycle_0"]["de_wm_icon"]
93 | if de_wm_icon == "on":
94 | de_wm_icon = computer.desktopid
95 | else:
96 | de_wm_icon = "off"
97 | if args.debug:
98 | print("cycle 0")
99 |
100 | run.try_update(
101 | key,
102 | state=bottom_line,
103 | details=top_line,
104 | large_image="big",
105 | large_text=computer.osinfo,
106 | small_image=de_wm_icon,
107 | small_text=computer.dewmid,
108 | start=computer.uptime,
109 | )
110 | if args.debug:
111 | print("appid: %s" % computer.osinfoid)
112 | config_time = run.config["cycle_0"]["time"]
113 | if args.time:
114 | time.sleep(int(args.time))
115 | elif args.nohost and args.nohardware and args.noshell:
116 | time.sleep(9999)
117 | elif config_time:
118 | time.sleep(int(config_time))
119 | else:
120 | time.sleep(30)
121 | run.try_clear(key)
122 |
123 |
124 | def cycle1(run: Run_rpc, key: str, computer: Computer):
125 | top_line = run.config["cycle_1"]["top_line"]
126 | if top_line == "gpu":
127 | top_line = computer.gpu
128 | elif top_line == "cpu":
129 | top_line = computer.cpu
130 | elif top_line == "mem":
131 | top_line = computer.memory
132 | elif top_line == "disk":
133 | top_line = computer.disks
134 | bottom_line = run.config["cycle_1"]["bottom_line"]
135 | if bottom_line == "gpu":
136 | bottom_line = computer.gpu
137 | elif bottom_line == "cpu":
138 | bottom_line = computer.cpu
139 | elif bottom_line == "mem":
140 | bottom_line = computer.memory
141 | elif bottom_line == "disk":
142 | bottom_line = computer.disks
143 | gpu_icon = run.config["cycle_1"]["gpu_icon"]
144 | if gpu_icon == "on":
145 | gpu_icon = computer.gpuid
146 | else:
147 | gpu_icon = "off"
148 | if args.debug:
149 | print("cycle 1")
150 | run.try_update(
151 | key,
152 | state=bottom_line,
153 | details=top_line,
154 | large_image="big",
155 | large_text=computer.cpu,
156 | small_image=gpu_icon,
157 | small_text=computer.gpu,
158 | start=computer.uptime,
159 | )
160 | if args.debug:
161 | print("appid: %s" % computer.cpuid)
162 | config_time = run.config["cycle_1"]["time"]
163 | if args.time:
164 | time.sleep(int(args.time))
165 | elif args.nodistro and args.noshell and args.nohost:
166 | time.sleep(9999)
167 | elif config_time:
168 | time.sleep(int(config_time))
169 | else:
170 | time.sleep(30)
171 | run.try_clear(key)
172 |
173 |
174 | def cycle2(run: Run_rpc, key: str, computer: Computer):
175 | top_line = run.config["cycle_2"]["top_line"]
176 | if top_line == "font":
177 | top_line = computer.terminal
178 | elif top_line == "shell":
179 | top_line = computer.shellid
180 | elif top_line == "theme":
181 | top_line = computer.theme
182 | bottom_line = run.config["cycle_2"]["bottom_line"]
183 | if bottom_line == "font":
184 | bottom_line = computer.terminal
185 | elif bottom_line == "shell":
186 | bottom_line = computer.shell
187 | elif bottom_line == "theme":
188 | bottom_line = computer.theme
189 | shell_icon = run.config["cycle_2"]["shell_icon"]
190 | if shell_icon == "on":
191 | shell_icon = computer.shellid
192 | else:
193 | shell_icon = "off"
194 | if args.debug:
195 | print("cycle 2")
196 |
197 | run.try_update(
198 | key,
199 | state=bottom_line,
200 | details=top_line,
201 | large_image="big",
202 | large_text=computer.terminal,
203 | small_image=shell_icon,
204 | small_text=computer.shell,
205 | start=computer.uptime,
206 | )
207 | if args.debug:
208 | print("appid: %s" % computer.osinfoid)
209 |
210 | config_time = run.config["cycle_2"]["time"]
211 |
212 | if args.time:
213 | time.sleep(int(args.time))
214 | elif args.nodistro and args.nohardware and args.nohost:
215 | time.sleep(9999)
216 | elif config_time:
217 | time.sleep(int(config_time))
218 | else:
219 | time.sleep(30)
220 | run.try_clear(key)
221 |
222 |
223 | def cycle3(run: Run_rpc, key: str, computer: Computer):
224 | # if not then forget it
225 | if computer.host != "Host: N/A" and computer.motherboard != "Motherboard: N/A":
226 | top_line = run.config["cycle_3"]["top_line"]
227 | if top_line == "battery":
228 | top_line = computer.battery
229 | elif top_line == "host":
230 | top_line = computer.motherboard
231 | elif top_line == "resolution":
232 | top_line = computer.resolution
233 | bottom_line = run.config["cycle_3"]["bottom_line"]
234 | if bottom_line == "resolution":
235 | bottom_line = computer.resolution
236 | elif bottom_line == "host":
237 | bottom_line = computer.motherboard
238 | elif bottom_line == "battery":
239 | bottom_line = computer.battery
240 | lapordesk_icon = run.config["cycle_3"]["lapordesk_icon"]
241 | if lapordesk_icon == "on":
242 | lapordesk_icon = computer.lapordesk
243 | else:
244 | lapordesk_icon = "off"
245 | if args.debug:
246 | print("cycle 3")
247 | run.try_update(
248 | key,
249 | state=computer.resolution,
250 | details=computer.battery,
251 | large_image="big",
252 | large_text=computer.motherboard,
253 | small_image=lapordesk_icon,
254 | small_text=computer.lapordesk,
255 | start=computer.uptime,
256 | )
257 | if args.debug:
258 | print("appid: %s" % computer.hostappid)
259 | config_time = run.config["cycle_3"]["time"]
260 | if args.time:
261 | time.sleep(int(args.time))
262 | elif args.nodistro and args.nohardware and args.noshell:
263 | time.sleep(9999)
264 | elif config_time:
265 | time.sleep(int(config_time))
266 | else:
267 | time.sleep(30)
268 | # back from whence you came
269 | run.try_clear(key)
270 |
--------------------------------------------------------------------------------
/fetch_cord/debugger.py:
--------------------------------------------------------------------------------
1 | # from __future__ import annotations
2 |
3 | from typing import List
4 |
5 | from .computer.Computer import Computer
6 | from .computer.cpu.Cpu_interface import Cpu_interface
7 |
8 |
9 | def run_debug(computer: Computer):
10 | print("----out.py----\n")
11 | print("----DE/WM----")
12 | if not computer.neofetchwin:
13 | print("deid: %s" % computer.deid)
14 | print("wmid: %s" % computer.wmid)
15 | try:
16 | print("wmline item 0: %s" % computer.wm)
17 | except IndexError:
18 | pass
19 | print("\n----TERMINAL----\n")
20 | print("fontline: %s" % computer.font)
21 | print("termid: %s" % computer.terminalid)
22 | print("termline item 0: %s" % computer.terminal)
23 | print("themeline: %s" % computer.theme)
24 | if computer.host != "Host: N/A":
25 | print("\n----HOST INFO----\n")
26 | print("hostline: %s" % computer.host)
27 | if computer.battery != computer.host:
28 | print("batteryline: %s" % computer.battery)
29 | print("resline: %s" % computer.resolution)
30 | print("\n----GPU INFO----\n")
31 | print("gpuinfo: %s" % computer.gpu)
32 | print("gpuvendor: %s" % computer.gpuid)
33 | print("\n----CPU INFO----\n")
34 | cpu: List[Cpu_interface] = computer.get_component("CPU:")
35 | if cpu:
36 | print("cpuvendor: %s" % cpu[0].vendor)
37 | print("cpumodel: %s" % cpu[0].model)
38 | print("cpuinfo: %s" % cpu[0].info)
39 | print("cpuline item 0: %s" % computer.cpu)
40 | print("memline: %s" % computer.memory)
41 | print("\n----OS INFO----\n")
42 | print("sysosline: %s" % computer.osinfo)
43 | print("sysosid: %s" % computer.osinfoid)
44 | print("diskline: %s" % computer.disks)
45 | if computer.os != "windows":
46 | print("packagesline item 0: %s" % computer.packages)
47 |
48 |
49 | def test_debug(computer: Computer):
50 | print("\n----testing.py----")
51 | if computer.os != "windows":
52 | print("----DE/WM----\n")
53 | print("deid: %s" % computer.deid)
54 | print("wmid: %s" % computer.wmid)
55 | print("\n----TERMINAL/SHELL----\n")
56 | print("termid: %s" % computer.terminalid)
57 | print("shellid: %s" % computer.shellid)
58 | print("\n----HOST INFO----\n")
59 | print("hostid: %s" % computer.hostid)
60 | else:
61 | print("moboid: %s" % computer.motherboardid)
62 | print("moboline: %s" % computer.motherboard)
63 | print("\n----GPU INFO----\n")
64 | print("gpuvendor: %s" % computer.gpuid)
65 | print("\n----CPU INFO----\n")
66 | cpu = computer.get_component("CPU:")
67 | if cpu:
68 | print("cpumodel: %s\n" % cpu[0].model)
69 |
70 |
71 | def run_rpc_debug(computer: Computer):
72 | print("----run_rpc----\n")
73 | print("uptime in epoch: %s" % computer.uptime)
74 | print("cpuid: %s" % computer.osinfoid)
75 | print("cpuappid: %s" % computer.cpuid)
76 | if computer.os != "windows":
77 | print("termappid: %s" % computer.terminalid)
78 | if computer.host != "Host: N/A":
79 | print("hostappid: %s" % computer.hostappid)
80 | print(computer.packages)
81 |
82 | run_debug(computer)
83 | test_debug(computer)
--------------------------------------------------------------------------------
/fetch_cord/resources/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fetchcord/FetchCord/3833c0f1464fb5703e712db4ebf0e7f88f22a829/fetch_cord/resources/__init__.py
--------------------------------------------------------------------------------
/fetch_cord/resources/default.conf:
--------------------------------------------------------------------------------
1 | # See this wiki page for more info:
2 | # https://github.com/dylanaraps/neofetch/wiki/Customizing-Info
3 | print_info() {
4 | info title
5 | info underline
6 |
7 | info "OS" distro
8 | info "Host" model
9 | info "Kernel" kernel
10 | info "Uptime" uptime
11 | info "Packages" packages
12 | info "Shell" shell
13 | info "Resolution" resolution
14 | info "DE" de
15 | info "WM" wm
16 | info "WM Theme" wm_theme
17 | info "Theme" theme
18 | info "Icons" icons
19 | info "Terminal" term
20 | info "Terminal Font" term_font
21 | info "CPU" cpu
22 | info "GPU" gpu
23 | info "Memory" memory
24 | info "Battery" battery
25 | info "Disk" disk
26 |
27 | # info "GPU Driver" gpu_driver # Linux/macOS only
28 | # info "CPU Usage" cpu_usage
29 | # info "Disk" disk
30 | # info "Battery" battery
31 | # info "Font" font
32 | # info "Song" song
33 | # [[ "$player" ]] && prin "Music Player" "$player"
34 | # info "Local IP" local_ip
35 | # info "Public IP" public_ip
36 | # info "Users" users
37 | # info "Locale" locale # This only works on glibc systems.
38 |
39 | info cols
40 | }
41 |
42 | # Title
43 |
44 |
45 | # Hide/Show Fully qualified domain name.
46 | #
47 | # Default: 'off'
48 | # Values: 'on', 'off'
49 | # Flag: --title_fqdn
50 | title_fqdn="off"
51 |
52 |
53 | # Kernel
54 |
55 |
56 | # Shorten the output of the kernel function.
57 | #
58 | # Default: 'on'
59 | # Values: 'on', 'off'
60 | # Flag: --kernel_shorthand
61 | # Supports: Everything except *BSDs (except PacBSD and PC-BSD)
62 | #
63 | # Example:
64 | # on: '4.8.9-1-ARCH'
65 | # off: 'Linux 4.8.9-1-ARCH'
66 | kernel_shorthand="on"
67 |
68 |
69 | # Distro
70 |
71 |
72 | # Shorten the output of the distro function
73 | #
74 | # Default: 'off'
75 | # Values: 'on', 'tiny', 'off'
76 | # Flag: --distro_shorthand
77 | # Supports: Everything except Windows and Haiku
78 | distro_shorthand="off"
79 |
80 | # Show/Hide OS Architecture.
81 | # Show 'x86_64', 'x86' and etc in 'Distro:' output.
82 | #
83 | # Default: 'on'
84 | # Values: 'on', 'off'
85 | # Flag: --os_arch
86 | #
87 | # Example:
88 | # on: 'Arch Linux x86_64'
89 | # off: 'Arch Linux'
90 | os_arch="on"
91 |
92 |
93 | # Uptime
94 |
95 |
96 | # Shorten the output of the uptime function
97 | #
98 | # Default: 'on'
99 | # Values: 'on', 'tiny', 'off'
100 | # Flag: --uptime_shorthand
101 | #
102 | # Example:
103 | # on: '2 days, 10 hours, 3 mins'
104 | # tiny: '2d 10h 3m'
105 | # off: '2 days, 10 hours, 3 minutes'
106 | uptime_shorthand="on"
107 |
108 |
109 | # Memory
110 |
111 |
112 | # Show memory pecentage in output.
113 | #
114 | # Default: 'off'
115 | # Values: 'on', 'off'
116 | # Flag: --memory_percent
117 | #
118 | # Example:
119 | # on: '1801MiB / 7881MiB (22%)'
120 | # off: '1801MiB / 7881MiB'
121 | memory_percent="off"
122 |
123 |
124 | # Packages
125 |
126 |
127 | # Show/Hide Package Manager names.
128 | #
129 | # Default: 'tiny'
130 | # Values: 'on', 'tiny' 'off'
131 | # Flag: --package_managers
132 | #
133 | # Example:
134 | # on: '998 (pacman), 8 (flatpak), 4 (snap)'
135 | # tiny: '908 (pacman, flatpak, snap)'
136 | # off: '908'
137 | package_managers="on"
138 |
139 |
140 | # Shell
141 |
142 |
143 | # Show the path to $SHELL
144 | #
145 | # Default: 'off'
146 | # Values: 'on', 'off'
147 | # Flag: --shell_path
148 | #
149 | # Example:
150 | # on: '/bin/bash'
151 | # off: 'bash'
152 | shell_path="off"
153 |
154 | # Show $SHELL version
155 | #
156 | # Default: 'on'
157 | # Values: 'on', 'off'
158 | # Flag: --shell_version
159 | #
160 | # Example:
161 | # on: 'bash 4.4.5'
162 | # off: 'bash'
163 | shell_version="on"
164 |
165 |
166 | # CPU
167 |
168 |
169 | # CPU speed type
170 | #
171 | # Default: 'bios_limit'
172 | # Values: 'scaling_cur_freq', 'scaling_min_freq', 'scaling_max_freq', 'bios_limit'.
173 | # Flag: --speed_type
174 | # Supports: Linux with 'cpufreq'
175 | # NOTE: Any file in '/sys/devices/system/cpu/cpu0/cpufreq' can be used as a value.
176 | speed_type="bios_limit"
177 |
178 | # CPU speed shorthand
179 | #
180 | # Default: 'off'
181 | # Values: 'on', 'off'.
182 | # Flag: --speed_shorthand
183 | # NOTE: This flag is not supported in systems with CPU speed less than 1 GHz
184 | #
185 | # Example:
186 | # on: 'i7-6500U (4) @ 3.1GHz'
187 | # off: 'i7-6500U (4) @ 3.100GHz'
188 | speed_shorthand="off"
189 |
190 | # Enable/Disable CPU brand in output.
191 | #
192 | # Default: 'on'
193 | # Values: 'on', 'off'
194 | # Flag: --cpu_brand
195 | #
196 | # Example:
197 | # on: 'Intel i7-6500U'
198 | # off: 'i7-6500U (4)'
199 | cpu_brand="on"
200 |
201 | # CPU Speed
202 | # Hide/Show CPU speed.
203 | #
204 | # Default: 'on'
205 | # Values: 'on', 'off'
206 | # Flag: --cpu_speed
207 | #
208 | # Example:
209 | # on: 'Intel i7-6500U (4) @ 3.1GHz'
210 | # off: 'Intel i7-6500U (4)'
211 | cpu_speed="on"
212 |
213 | # CPU Cores
214 | # Display CPU cores in output
215 | #
216 | # Default: 'logical'
217 | # Values: 'logical', 'physical', 'off'
218 | # Flag: --cpu_cores
219 | # Support: 'physical' doesn't work on BSD.
220 | #
221 | # Example:
222 | # logical: 'Intel i7-6500U (4) @ 3.1GHz' (All virtual cores)
223 | # physical: 'Intel i7-6500U (2) @ 3.1GHz' (All physical cores)
224 | # off: 'Intel i7-6500U @ 3.1GHz'
225 | cpu_cores="logical"
226 |
227 | # CPU Temperature
228 | # Hide/Show CPU temperature.
229 | # Note the temperature is added to the regular CPU function.
230 | #
231 | # Default: 'off'
232 | # Values: 'C', 'F', 'off'
233 | # Flag: --cpu_temp
234 | # Supports: Linux, BSD
235 | # NOTE: For FreeBSD and NetBSD-based systems, you'll need to enable
236 | # coretemp kernel module. This only supports newer Intel processors.
237 | #
238 | # Example:
239 | # C: 'Intel i7-6500U (4) @ 3.1GHz [27.2°C]'
240 | # F: 'Intel i7-6500U (4) @ 3.1GHz [82.0°F]'
241 | # off: 'Intel i7-6500U (4) @ 3.1GHz'
242 | cpu_temp="off"
243 |
244 |
245 | # GPU
246 |
247 |
248 | # Enable/Disable GPU Brand
249 | #
250 | # Default: 'on'
251 | # Values: 'on', 'off'
252 | # Flag: --gpu_brand
253 | #
254 | # Example:
255 | # on: 'AMD HD 7950'
256 | # off: 'HD 7950'
257 | gpu_brand="on"
258 |
259 | # Which GPU to display
260 | #
261 | # Default: 'all'
262 | # Values: 'all', 'dedicated', 'integrated'
263 | # Flag: --gpu_type
264 | # Supports: Linux
265 | #
266 | # Example:
267 | # all:
268 | # GPU1: AMD HD 7950
269 | # GPU2: Intel Integrated Graphics
270 | #
271 | # dedicated:
272 | # GPU1: AMD HD 7950
273 | #
274 | # integrated:
275 | # GPU1: Intel Integrated Graphics
276 | gpu_type="all"
277 |
278 |
279 | # Resolution
280 |
281 |
282 | # Display refresh rate next to each monitor
283 | # Default: 'off'
284 | # Values: 'on', 'off'
285 | # Flag: --refresh_rate
286 | # Supports: Doesn't work on Windows.
287 | #
288 | # Example:
289 | # on: '1920x1080 @ 60Hz'
290 | # off: '1920x1080'
291 | refresh_rate="off"
292 |
293 |
294 | # Gtk Theme / Icons / Font
295 |
296 |
297 | # Shorten output of GTK Theme / Icons / Font
298 | #
299 | # Default: 'off'
300 | # Values: 'on', 'off'
301 | # Flag: --gtk_shorthand
302 | #
303 | # Example:
304 | # on: 'Numix, Adwaita'
305 | # off: 'Numix [GTK2], Adwaita [GTK3]'
306 | gtk_shorthand="off"
307 |
308 |
309 | # Enable/Disable gtk2 Theme / Icons / Font
310 | #
311 | # Default: 'on'
312 | # Values: 'on', 'off'
313 | # Flag: --gtk2
314 | #
315 | # Example:
316 | # on: 'Numix [GTK2], Adwaita [GTK3]'
317 | # off: 'Adwaita [GTK3]'
318 | gtk2="on"
319 |
320 | # Enable/Disable gtk3 Theme / Icons / Font
321 | #
322 | # Default: 'on'
323 | # Values: 'on', 'off'
324 | # Flag: --gtk3
325 | #
326 | # Example:
327 | # on: 'Numix [GTK2], Adwaita [GTK3]'
328 | # off: 'Numix [GTK2]'
329 | gtk3="on"
330 |
331 |
332 | # IP Address
333 |
334 |
335 | # Website to ping for the public IP
336 | #
337 | # Default: 'http://ident.me'
338 | # Values: 'url'
339 | # Flag: --ip_host
340 | public_ip_host="http://ident.me"
341 |
342 | # Public IP timeout.
343 | #
344 | # Default: '2'
345 | # Values: 'int'
346 | # Flag: --ip_timeout
347 | public_ip_timeout=2
348 |
349 |
350 | # Desktop Environment
351 |
352 |
353 | # Show Desktop Environment version
354 | #
355 | # Default: 'off'
356 | # Values: 'on', 'off'
357 | # Flag: --de_version
358 | de_version="on"
359 |
360 |
361 | # Disk
362 |
363 |
364 | # Which disks to display.
365 | # The values can be any /dev/sdXX, mount point or directory.
366 | # NOTE: By default we only show the disk info for '/'.
367 | #
368 | # Default: '/'
369 | # Values: '/', '/dev/sdXX', '/path/to/drive'.
370 | # Flag: --disk_show
371 | #
372 | # Example:
373 | # disk_show=('/' '/dev/sdb1'):
374 | # 'Disk (/): 74G / 118G (66%)'
375 | # 'Disk (/mnt/Videos): 823G / 893G (93%)'
376 | #
377 | # disk_show=('/'):
378 | # 'Disk (/): 74G / 118G (66%)'
379 | #
380 | disk_show=('/')
381 |
382 | # Disk subtitle.
383 | # What to append to the Disk subtitle.
384 | #
385 | # Default: 'mount'
386 | # Values: 'mount', 'name', 'dir', 'none'
387 | # Flag: --disk_subtitle
388 | #
389 | # Example:
390 | # name: 'Disk (/dev/sda1): 74G / 118G (66%)'
391 | # 'Disk (/dev/sdb2): 74G / 118G (66%)'
392 | #
393 | # mount: 'Disk (/): 74G / 118G (66%)'
394 | # 'Disk (/mnt/Local Disk): 74G / 118G (66%)'
395 | # 'Disk (/mnt/Videos): 74G / 118G (66%)'
396 | #
397 | # dir: 'Disk (/): 74G / 118G (66%)'
398 | # 'Disk (Local Disk): 74G / 118G (66%)'
399 | # 'Disk (Videos): 74G / 118G (66%)'
400 | #
401 | # none: 'Disk: 74G / 118G (66%)'
402 | # 'Disk: 74G / 118G (66%)'
403 | # 'Disk: 74G / 118G (66%)'
404 | disk_subtitle="mount"
405 |
406 | # Disk percent.
407 | # Show/Hide disk percent.
408 | #
409 | # Default: 'on'
410 | # Values: 'on', 'off'
411 | # Flag: --disk_percent
412 | #
413 | # Example:
414 | # on: 'Disk (/): 74G / 118G (66%)'
415 | # off: 'Disk (/): 74G / 118G'
416 | disk_percent="on"
417 |
418 |
419 | # Song
420 |
421 |
422 | # Manually specify a music player.
423 | #
424 | # Default: 'auto'
425 | # Values: 'auto', 'player-name'
426 | # Flag: --music_player
427 | #
428 | # Available values for 'player-name':
429 | #
430 | # amarok
431 | # audacious
432 | # banshee
433 | # bluemindo
434 | # clementine
435 | # cmus
436 | # deadbeef
437 | # deepin-music
438 | # dragon
439 | # elisa
440 | # exaile
441 | # gnome-music
442 | # gmusicbrowser
443 | # gogglesmm
444 | # guayadeque
445 | # io.elementary.music
446 | # iTunes
447 | # juk
448 | # lollypop
449 | # mocp
450 | # mopidy
451 | # mpd
452 | # muine
453 | # netease-cloud-music
454 | # pogo
455 | # pragha
456 | # qmmp
457 | # quodlibet
458 | # rhythmbox
459 | # sayonara
460 | # smplayer
461 | # spotify
462 | # strawberry
463 | # tomahawk
464 | # vlc
465 | # xmms2d
466 | # xnoise
467 | # yarock
468 | music_player="auto"
469 |
470 | # Format to display song information.
471 | #
472 | # Default: '%artist% - %album% - %title%'
473 | # Values: '%artist%', '%album%', '%title%'
474 | # Flag: --song_format
475 | #
476 | # Example:
477 | # default: 'Song: Jet - Get Born - Sgt Major'
478 | song_format="%artist% - %album% - %title%"
479 |
480 | # Print the Artist, Album and Title on separate lines
481 | #
482 | # Default: 'off'
483 | # Values: 'on', 'off'
484 | # Flag: --song_shorthand
485 | #
486 | # Example:
487 | # on: 'Artist: The Fratellis'
488 | # 'Album: Costello Music'
489 | # 'Song: Chelsea Dagger'
490 | #
491 | # off: 'Song: The Fratellis - Costello Music - Chelsea Dagger'
492 | song_shorthand="off"
493 |
494 | # 'mpc' arguments (specify a host, password etc).
495 | #
496 | # Default: ''
497 | # Example: mpc_args=(-h HOST -P PASSWORD)
498 | mpc_args=()
499 |
500 |
501 | # Text Colors
502 |
503 |
504 | # Text Colors
505 | #
506 | # Default: 'distro'
507 | # Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num'
508 | # Flag: --colors
509 | #
510 | # Each number represents a different part of the text in
511 | # this order: 'title', '@', 'underline', 'subtitle', 'colon', 'info'
512 | #
513 | # Example:
514 | # colors=(distro) - Text is colored based on Distro colors.
515 | # colors=(4 6 1 8 8 6) - Text is colored in the order above.
516 | colors=(distro)
517 |
518 |
519 | # Text Options
520 |
521 |
522 | # Toggle bold text
523 | #
524 | # Default: 'on'
525 | # Values: 'on', 'off'
526 | # Flag: --bold
527 | bold="on"
528 |
529 | # Enable/Disable Underline
530 | #
531 | # Default: 'on'
532 | # Values: 'on', 'off'
533 | # Flag: --underline
534 | underline_enabled="on"
535 |
536 | # Underline character
537 | #
538 | # Default: '-'
539 | # Values: 'string'
540 | # Flag: --underline_char
541 | underline_char="-"
542 |
543 |
544 | # Info Separator
545 | # Replace the default separator with the specified string.
546 | #
547 | # Default: ':'
548 | # Flag: --separator
549 | #
550 | # Example:
551 | # separator="->": 'Shell-> bash'
552 | # separator=" =": 'WM = dwm'
553 | separator=":"
554 |
555 |
556 | # Color Blocks
557 |
558 |
559 | # Color block range
560 | # The range of colors to print.
561 | #
562 | # Default: '0', '15'
563 | # Values: 'num'
564 | # Flag: --block_range
565 | #
566 | # Example:
567 | #
568 | # Display colors 0-7 in the blocks. (8 colors)
569 | # neofetch --block_range 0 7
570 | #
571 | # Display colors 0-15 in the blocks. (16 colors)
572 | # neofetch --block_range 0 15
573 | block_range=(0 15)
574 |
575 | # Toggle color blocks
576 | #
577 | # Default: 'on'
578 | # Values: 'on', 'off'
579 | # Flag: --color_blocks
580 | color_blocks="on"
581 |
582 | # Color block width in spaces
583 | #
584 | # Default: '3'
585 | # Values: 'num'
586 | # Flag: --block_width
587 | block_width=3
588 |
589 | # Color block height in lines
590 | #
591 | # Default: '1'
592 | # Values: 'num'
593 | # Flag: --block_height
594 | block_height=1
595 |
596 | # Color Alignment
597 | #
598 | # Default: 'auto'
599 | # Values: 'auto', 'num'
600 | # Flag: --col_offset
601 | #
602 | # Number specifies how far from the left side of the terminal (in spaces) to
603 | # begin printing the columns, in case you want to e.g. center them under your
604 | # text.
605 | # Example:
606 | # col_offset="auto" - Default behavior of neofetch
607 | # col_offset=7 - Leave 7 spaces then print the colors
608 | col_offset="auto"
609 |
610 | # Progress Bars
611 |
612 |
613 | # Bar characters
614 | #
615 | # Default: '-', '='
616 | # Values: 'string', 'string'
617 | # Flag: --bar_char
618 | #
619 | # Example:
620 | # neofetch --bar_char 'elapsed' 'total'
621 | # neofetch --bar_char '-' '='
622 | bar_char_elapsed="-"
623 | bar_char_total="="
624 |
625 | # Toggle Bar border
626 | #
627 | # Default: 'on'
628 | # Values: 'on', 'off'
629 | # Flag: --bar_border
630 | bar_border="on"
631 |
632 | # Progress bar length in spaces
633 | # Number of chars long to make the progress bars.
634 | #
635 | # Default: '15'
636 | # Values: 'num'
637 | # Flag: --bar_length
638 | bar_length=15
639 |
640 | # Progress bar colors
641 | # When set to distro, uses your distro's logo colors.
642 | #
643 | # Default: 'distro', 'distro'
644 | # Values: 'distro', 'num'
645 | # Flag: --bar_colors
646 | #
647 | # Example:
648 | # neofetch --bar_colors 3 4
649 | # neofetch --bar_colors distro 5
650 | bar_color_elapsed="distro"
651 | bar_color_total="distro"
652 |
653 |
654 | # Info display
655 | # Display a bar with the info.
656 | #
657 | # Default: 'off'
658 | # Values: 'bar', 'infobar', 'barinfo', 'off'
659 | # Flags: --cpu_display
660 | # --memory_display
661 | # --battery_display
662 | # --disk_display
663 | #
664 | # Example:
665 | # bar: '[---=======]'
666 | # infobar: 'info [---=======]'
667 | # barinfo: '[---=======] info'
668 | # off: 'info'
669 | cpu_display="off"
670 | memory_display="off"
671 | battery_display="off"
672 | disk_display="off"
673 |
674 |
675 | # Backend Settings
676 |
677 |
678 | # Image backend.
679 | #
680 | # Default: 'ascii'
681 | # Values: 'ascii', 'caca', 'chafa', 'jp2a', 'iterm2', 'off',
682 | # 'termpix', 'pixterm', 'tycat', 'w3m', 'kitty'
683 | # Flag: --backend
684 | image_backend="ascii"
685 |
686 | # Image Source
687 | #
688 | # Which image or ascii file to display.
689 | #
690 | # Default: 'auto'
691 | # Values: 'auto', 'ascii', 'wallpaper', '/path/to/img', '/path/to/ascii', '/path/to/dir/'
692 | # 'command output (neofetch --ascii "$(fortune | cowsay -W 30)")'
693 | # Flag: --source
694 | #
695 | # NOTE: 'auto' will pick the best image source for whatever image backend is used.
696 | # In ascii mode, distro ascii art will be used and in an image mode, your
697 | # wallpaper will be used.
698 | image_source="auto"
699 |
700 |
701 | # Ascii Options
702 |
703 |
704 | # Ascii distro
705 | # Which distro's ascii art to display.
706 | #
707 | # Default: 'auto'
708 | # Values: 'auto', 'distro_name'
709 | # Flag: --ascii_distro
710 | # NOTE: AIX, Alpine, Anarchy, Android, Antergos, antiX, AOSC,
711 | # Apricity, ArcoLinux, ArchBox, ARCHlabs, ArchStrike,
712 | # XFerience, ArchMerge, Arch, Artix, Arya, Bedrock, Bitrig,
713 | # BlackArch, BLAG, BlankOn, BlueLight, bonsai, BSD,
714 | # BunsenLabs, Calculate, Carbs, CentOS, Chakra, ChaletOS,
715 | # Chapeau, Chrom*, Cleanjaro, ClearOS, Clear_Linux, Clover,
716 | # Condres, Container_Linux, CRUX, Cucumber, Debian, Deepin,
717 | # DesaOS, Devuan, DracOS, DragonFly, Drauger, Elementary,
718 | # EndeavourOS, Endless, EuroLinux, Exherbo, Fedora, Feren, FreeBSD,
719 | # FreeMiNT, Frugalware, Funtoo, GalliumOS, Gentoo, Pentoo,
720 | # gNewSense, GNU, GoboLinux, Grombyang, Guix, Haiku, Huayra,
721 | # Hyperbola, janus, Kali, KaOS, KDE_neon, Kibojoe, Kogaion,
722 | # Korora, KSLinux, Kubuntu, LEDE, LFS, Linux_Lite,
723 | # LMDE, Lubuntu, Lunar, macos, Mageia, MagpieOS, Mandriva,
724 | # Manjaro, Maui, Mer, Minix, LinuxMint, MX_Linux, Namib,
725 | # Neptune, NetBSD, Netrunner, Nitrux, NixOS, Nurunner,
726 | # NuTyX, OBRevenge, OpenBSD, OpenIndiana, OpenMandriva,
727 | # OpenWrt, osmc, Oracle, PacBSD, Parabola, Pardus, Parrot,
728 | # Parsix, TrueOS, PCLinuxOS, Peppermint, popos, Porteus,
729 | # PostMarketOS, Proxmox, Puppy, PureOS, Qubes, Radix, Raspbian,
730 | # Reborn_OS, Redstar, Redcore, Redhat, Refracted_Devuan, Regata,
731 | # Rosa, sabotage, Sabayon, Sailfish, SalentOS, Scientific, Septor,
732 | # SharkLinux, Siduction, Slackware, SliTaz, SmartOS, Solus,
733 | # Source_Mage, Sparky, Star, SteamOS, SunOS, openSUSE_Leap,
734 | # openSUSE_Tumbleweed, openSUSE, SwagArch, Tails, Trisquel,
735 | # Ubuntu-Budgie, Ubuntu-GNOME, Ubuntu-MATE, Ubuntu-Studio, Ubuntu,
736 | # Void, Obarun, windows10, Windows7, Xubuntu, Zorin, and IRIX
737 | # have ascii logos
738 | # NOTE: Arch, Ubuntu, Redhat, and Dragonfly have 'old' logo variants.
739 | # Use '{distro name}_old' to use the old logos.
740 | # NOTE: Ubuntu has flavor variants.
741 | # Change this to Lubuntu, Kubuntu, Xubuntu, Ubuntu-GNOME,
742 | # Ubuntu-Studio, Ubuntu-Mate or Ubuntu-Budgie to use the flavors.
743 | # NOTE: Arcolinux, Dragonfly, Fedora, Alpine, Arch, Ubuntu,
744 | # CRUX, Debian, Gentoo, FreeBSD, Mac, NixOS, OpenBSD, android,
745 | # Antrix, CentOS, Cleanjaro, ElementaryOS, GUIX, Hyperbola,
746 | # Manjaro, MXLinux, NetBSD, Parabola, POP_OS, PureOS,
747 | # Slackware, SunOS, LinuxLite, OpenSUSE, Raspbian,
748 | # postmarketOS, and Void have a smaller logo variant.
749 | # Use '{distro name}_small' to use the small variants.
750 | ascii_distro="auto"
751 |
752 | # Ascii Colors
753 | #
754 | # Default: 'distro'
755 | # Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num'
756 | # Flag: --ascii_colors
757 | #
758 | # Example:
759 | # ascii_colors=(distro) - Ascii is colored based on Distro colors.
760 | # ascii_colors=(4 6 1 8 8 6) - Ascii is colored using these colors.
761 | ascii_colors=(distro)
762 |
763 | # Bold ascii logo
764 | # Whether or not to bold the ascii logo.
765 | #
766 | # Default: 'on'
767 | # Values: 'on', 'off'
768 | # Flag: --ascii_bold
769 | ascii_bold="on"
770 |
771 |
772 | # Image Options
773 |
774 |
775 | # Image loop
776 | # Setting this to on will make neofetch redraw the image constantly until
777 | # Ctrl+C is pressed. This fixes display issues in some terminal emulators.
778 | #
779 | # Default: 'off'
780 | # Values: 'on', 'off'
781 | # Flag: --loop
782 | image_loop="off"
783 |
784 | # Thumbnail directory
785 | #
786 | # Default: '~/.cache/thumbnails/neofetch'
787 | # Values: 'dir'
788 | thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch"
789 |
790 | # Crop mode
791 | #
792 | # Default: 'normal'
793 | # Values: 'normal', 'fit', 'fill'
794 | # Flag: --crop_mode
795 | #
796 | # See this wiki page to learn about the fit and fill options.
797 | # https://github.com/dylanaraps/neofetch/wiki/What-is-Waifu-Crop%3F
798 | crop_mode="normal"
799 |
800 | # Crop offset
801 | # Note: Only affects 'normal' crop mode.
802 | #
803 | # Default: 'center'
804 | # Values: 'northwest', 'north', 'northeast', 'west', 'center'
805 | # 'east', 'southwest', 'south', 'southeast'
806 | # Flag: --crop_offset
807 | crop_offset="center"
808 |
809 | # Image size
810 | # The image is half the terminal width by default.
811 | #
812 | # Default: 'auto'
813 | # Values: 'auto', '00px', '00%', 'none'
814 | # Flags: --image_size
815 | # --size
816 | image_size="auto"
817 |
818 | # Gap between image and text
819 | #
820 | # Default: '3'
821 | # Values: 'num', '-num'
822 | # Flag: --gap
823 | gap=3
824 |
825 | # Image offsets
826 | # Only works with the w3m backend.
827 | #
828 | # Default: '0'
829 | # Values: 'px'
830 | # Flags: --xoffset
831 | # --yoffset
832 | yoffset=0
833 | xoffset=0
834 |
835 | # Image background color
836 | # Only works with the w3m backend.
837 | #
838 | # Default: ''
839 | # Values: 'color', 'blue'
840 | # Flag: --bg_color
841 | background_color=
842 |
843 |
844 | # Misc Options
845 |
846 | # Stdout mode
847 | # Turn off all colors and disables image backend (ASCII/Image).
848 | # Useful for piping into another command.
849 | # Default: 'off'
850 | # Values: 'on', 'off'
851 | stdout="off"
852 |
--------------------------------------------------------------------------------
/fetch_cord/resources/fetch_cord.conf:
--------------------------------------------------------------------------------
1 | [cycle_0]
2 |
3 | # Order to set info in discord presence, valid values are: kernel, packages
4 | top_line=kernel
5 | bottom_line=packages
6 | # show small_icon in Discord
7 | de_wm_icon=on
8 |
9 | # Duration to show this cycle
10 | # valid values are, 15, 30, 45, 60, 75, 90, 105, 120, 240, and 480
11 | time=30
12 |
13 | [cycle_1]
14 |
15 | # Order to set info in discord presence, valid values are: mem, gpu, cpu, and disk
16 | top_line=mem
17 | bottom_line=gpu
18 | # show small_icon in Discord
19 | gpu_icon=on
20 |
21 | # Duration to show this cycle
22 | # valid values are, 15, 30, 45, 60, 75, 90, 105, 120, 240, and 480
23 | time=30
24 |
25 | [cycle_2]
26 |
27 | # Order to set info in discord presence, valid values are: font, shell, and theme
28 | top_line=font
29 | bottom_line=shell
30 | # show small_icon in Discord
31 | shell_icon=on
32 |
33 | # Duration to show this cycle
34 | # valid values are, 15, 30, 45, 60, 75, 90, 105, 120, 240, and 480
35 | time=30
36 |
37 | [cycle_3]
38 |
39 | # Order to set info in discord presence, valid values are: battery, resolution, and host
40 | top_line=battery
41 | bottom_line=resolution
42 | # show small_icon in Discord
43 | lapordesk_icon=on
44 |
45 | # Duration to show this cycle
46 | # valid values are, 15, 30, 45, 60, 75, 90, 105, 120, 240, and 480
47 | time=30
--------------------------------------------------------------------------------
/fetch_cord/resources/fetchcord_ids.json:
--------------------------------------------------------------------------------
1 | {
2 | "map": {
3 | "GPU:": "gpu",
4 | "CPU:": "cpu",
5 | "Terminal:": "terminal",
6 | "Motherboard:": "motherboard",
7 | "Host:": "motherboard",
8 | "Shell:": "shell",
9 | "OS:": "distro",
10 | "DE:": "desktop",
11 | "WM:": "windowmanager",
12 | "Version:": "version"
13 | },
14 | "gpu": {
15 | "amd": "amd",
16 | "radeon": "amd",
17 | "amdnvidia": "nvidiaamd",
18 | "amdintel": "amdintel",
19 | "nvidia": "nvidia",
20 | "nvidiaamd": "nvidiaamd",
21 | "nvidiaintel": "nvidiaintel",
22 | "intel": "intel",
23 | "intelamd": "amdintel",
24 | "intelnvidia": "nvidiaintel",
25 | "vmware": "vmware",
26 | "virtio": "virtio",
27 | "cirrus": "cirrus",
28 | "unknown": "off"
29 | },
30 | "cpu": {
31 | "amd": {
32 | "ryzen 3": "741153175779803146",
33 | "ryzen 5": "741152732756312125",
34 | "ryzen 7": "740752899054895105",
35 | "ryzen 9": "741152930899427364",
36 | "ryzen threadripper": "742075019257184338",
37 | "a4 apu": "820717165329645618",
38 | "a6 apu": "820711517715693608",
39 | "a8 apu": "820715505437638708",
40 | "a9 apu": "820738634473930752",
41 | "a10 apu": "820726638635122740",
42 | "a12 apu": "820737378494054451",
43 | "fx apu": "820739431711113226",
44 | "athlon silver": "870365152401293452",
45 | "athlon gold": "870365152401293452"
46 | },
47 | "intel": {
48 | "intel i3": "741044208512532570",
49 | "intel i5": "741099939198926920",
50 | "intel i7": "741100300219187335",
51 | "intel i9": "741100622040006719",
52 | "intel pentium": "741203845706940467",
53 | "intel celeron": "742904581360713849",
54 | "pentium": "741203845706940467",
55 | "intel core 2 duo": "746527640382603375",
56 | "intel2 duo": "746527640382603375",
57 | "intel core 2 quad": "785615606438166544",
58 | "intel2 quad": "785615606438166544",
59 | "intel xeon": "749011141090607144"
60 | },
61 | "unknown": "742887089179197462"
62 | },
63 | "terminal": {
64 | "st": "741280043220861030",
65 | "kitty": "741285676250824725",
66 | "alacritty": "741291339945345045",
67 | "xterm": "741287143187546125",
68 | "konsole": "741286819676553258",
69 | "dolphin": "741286819676553258",
70 | "gnome-terminal": "741328861115056160",
71 | "cool-retro-term": "741731097498353794",
72 | "urxvt": "743246048968835092",
73 | "xfce4-terminal": "744332423072055296",
74 | "apple_terminal": "744950796298354689",
75 | "lxterminal": "745701997503840380",
76 | "yakuake": "741286819676553258",
77 | "mate-terminal": "746531413360377856",
78 | "terminus": "878027718132899901",
79 | "io.elementary.t": "878027718132899901",
80 | "windows terminal": "878034077444374559",
81 | "unknown": "745691250186911796"
82 | },
83 | "motherboard": {
84 | "asrock": "811349714946490408",
85 | "aorus": "749061181607772200",
86 | "inspiron": "743970870631858288",
87 | "latitude": "743970870631858288",
88 | "g3": "743970870631858288",
89 | "hp": "743971270395297852",
90 | "hewlett-packard": "743971270395297852",
91 | "J7D10ET": "743971270395297852",
92 | "tuf": "744330890343219262",
93 | "asus": "743936082780880928",
94 | "asustek": "743936082780880928",
95 | "acer": "744326890512318544",
96 | "KBL (Metapod_KL)": "744326890512318544",
97 | "thinkpad": "744326223412461630",
98 | "ideapad": "744326223412461630",
99 | "lenovo": "744326223412461630",
100 | "thinkcentre": "744326223412461630",
101 | "gigabyte": "746447043190456561",
102 | "Z370XP SLI": "746447043190456561",
103 | "Z390 GAMING X": "746447043190456561",
104 | "macbookair,": "748290608787095694",
105 | "macbookpro,": "750016315854553138",
106 | "aspire": "744326890512318544",
107 | "DL (Tulip_DA)": "744326890512318544",
108 | "hvm": "749014556604497972",
109 | "dell": "785620748021792788",
110 | "msi": "787106184783200266",
111 | "optiplex 780": "785620748021792788",
112 | "optiplex": "785620748021792788",
113 | "H310M A 2.0": "746447043190456561",
114 | "K53TA 1.0": "743936082780880928",
115 | "MS-7C02 1.0": "787106184783200266",
116 | "PE70 6QD REV:1.0": "787106184783200266",
117 | "unknown": "742887089179197462"
118 | },
119 | "shell": {
120 | "fish": "fish",
121 | "zsh": "zsh",
122 | "bash": "bash",
123 | "tcsh": "tcsh",
124 | "ruby": "ruby",
125 | "unknown": "unknown"
126 | },
127 | "distro": {
128 | "elementary": "877994542912114718",
129 | "ubuntu": "740434138036699178",
130 | "opensuseleap": "740156532137787433",
131 | "arch": "740476198437650473",
132 | "arco": "745435867971321866",
133 | "artix": "741918141248045107",
134 | "fedora": "740485660703719464",
135 | "void": "740484961353597039",
136 | "gentoo/linux": "740484380652208140",
137 | "funtoo": "740484380652208140",
138 | "centos": "740483295388631071",
139 | "debian": "740490017218232392",
140 | "opensusetumbleweed": "742180413132505088",
141 | "manjaro": "740614258177605642",
142 | "linuxmint": "740633577481568317",
143 | "lmde": "741726946588622988",
144 | "pop!_os": "740660055925587978",
145 | "endeavouros": "740809641545564170",
146 | "windows10": "741949889465942099",
147 | "windows7": "741952383512346696",
148 | "windows8": "741952179488948324",
149 | "windows8.1": "741952065294827520",
150 | "windows11": "865716441431932959",
151 | "nixos": "744644133494325329",
152 | "instantos": "744784599653285938",
153 | "freebsd": "745054697047457822",
154 | "solus": "745689115944681683",
155 | "zorin": "745689865798156379",
156 | "amazon": "749014983920320583",
157 | "bedrock": "749015250904416287",
158 | "garuda": "820649067695833118",
159 | "parrotos": "852597254509297684",
160 | "rebornos": "852619769551257650",
161 | "mageia": "852639226445299752",
162 | "unknown": "742993278143692821"
163 | },
164 | "desktop": {
165 | "kde": "kde",
166 | "plasma": "plasma",
167 | "xfce": "xfce",
168 | "budgie": "budgie",
169 | "gnome": "gnome",
170 | "deepin": "deepin",
171 | "cinnamon": "cinnamon",
172 | "mate": "mate",
173 | "aero": "aero",
174 | "pantheon": "pantheon",
175 | "explorer": "explorer",
176 | "unknown": "unknown"
177 | },
178 | "windowmanager": {
179 | "dwm": "dwm",
180 | "i3": "i3",
181 | "awesome": "awesome",
182 | "enlightenment": "enlightenment",
183 | "bspwm": "bspwm",
184 | "xmonad": "xmonad",
185 | "sway": "sway",
186 | "openbox": "openbox",
187 | "herbstluftwm": "herbstluftwm",
188 | "unknown": "unknown"
189 | },
190 | "version": {
191 | "10.13": "hsierria",
192 | "10.14": "mojave",
193 | "10.15": "catalina",
194 | "unknown": "unknown"
195 | }
196 | }
--------------------------------------------------------------------------------
/fetch_cord/resources/systemd_service.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | from os import system
4 | from ..run_command import BashError, exec_bash
5 | from ..args import parse_args
6 | import sys
7 |
8 | args = parse_args()
9 |
10 |
11 | def systemd_cmd(cmd: str):
12 | try:
13 | print(exec_bash(f"systemctl --user {cmd} --now fetchcord"))
14 | except BashError as err:
15 | print(err)
16 | sys.exit(1)
17 |
18 |
19 | def install():
20 | try:
21 | exec_bash("mkdir -p ~/.local/share/systemd/user")
22 | except:
23 | print("Error : Cannot create directory...")
24 | sys.exit(1)
25 |
26 | try:
27 | exec_bash(
28 | f"wget -O ~/.local/share/systemd/user/fetchcord.service https://raw.githubusercontent.com/MrPotatoBobx/FetchCord/{'testing' if args.testing else 'master'}/systemd/fetchcord.service",
29 | )
30 | except:
31 | print("Error: Failed to download the service file.")
32 | sys.exit(1)
33 |
34 | systemd_cmd("enable")
35 |
36 | start()
37 |
38 |
39 | def uninstall():
40 | systemd_cmd("stop")
41 |
42 | systemd_cmd("disable")
43 |
44 | try:
45 | exec_bash("rm -f ~/.local/share/systemd/user/fetchcord.service")
46 | except:
47 | print("Error : Cannot remove service file...")
48 | sys.exit(1)
49 |
50 | sys.exit(0)
51 |
52 |
53 | def enable():
54 | systemd_cmd("enable")
55 | sys.exit(0)
56 |
57 |
58 | def disable():
59 | systemd_cmd("disable")
60 | sys.exit(0)
61 |
62 |
63 | def start():
64 | systemd_cmd("start")
65 | sys.exit(0)
66 |
67 |
68 | def stop():
69 | systemd_cmd("stop")
70 | sys.exit(0)
71 |
72 |
73 | def status():
74 | systemd_cmd("status")
75 | sys.exit(0)
--------------------------------------------------------------------------------
/fetch_cord/run_command.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 | from typing import List
4 | import subprocess
5 |
6 |
7 | def run_command(command: List[str], shell: bool = False):
8 | return subprocess.run(
9 | command, encoding="utf-8", stdout=subprocess.PIPE, shell=shell
10 | ).stdout
11 |
12 |
13 | class BashError(Exception):
14 | pass
15 |
16 |
17 | def exec_bash(command: str):
18 | try:
19 | out = (
20 | subprocess.check_output(["bash", "-c", command], stderr=subprocess.STDOUT)
21 | .decode("utf8")
22 | .strip()
23 | )
24 |
25 | except subprocess.CalledProcessError as e:
26 | out = e.stdout.decode("utf8")
27 | raise BashError("Failed to execute '%s' :\n%s" % (command, out))
28 | except FileNotFoundError as e:
29 | raise BashError("BASH not installed on your computer...")
30 |
31 | return out
32 |
--------------------------------------------------------------------------------
/fetch_cord/run_rpc.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 |
4 | from typing import Callable, Dict
5 | from pypresence import Presence, exceptions
6 | import time, sys
7 |
8 | # import info about system
9 | from .args import parse_args
10 | from .config import ConfigError, load_config
11 | from .computer.Computer import Computer
12 |
13 | args = parse_args()
14 |
15 |
16 | class Run_rpc:
17 | rpcs: Dict[str, Presence]
18 | config: Dict
19 |
20 | loops: Dict[str, Callable[['Run_rpc', str, Computer], None]] # Cannot use Run_rpc for type hinting unless doing the __future__.annotations import
21 | loops_indexes: Dict[int, str]
22 | poll_rate: int
23 | update: Callable
24 |
25 | def __init__(self):
26 | self.rpcs = {}
27 |
28 | try:
29 | self.config = load_config()
30 | except ConfigError as e:
31 | print("Error loading config file, using default values." % str(e))
32 |
33 | def set_loop(
34 | self, loops: Dict, loops_indexes: Dict, update: Callable, poll_rate: int = 3
35 | ):
36 | self.loops = loops
37 | self.loops_indexes = loops_indexes
38 |
39 | self.poll_rate = poll_rate
40 | self.update = update
41 |
42 | def run_loop(self, computer: Computer):
43 | try:
44 | loop = 0
45 | while True:
46 | for i in range(len(self.loops_indexes)):
47 | if loop == self.poll_rate:
48 | self.update()
49 | loop = 0
50 | try:
51 | client_id, func = self.loops[self.loops_indexes[i]]
52 |
53 | if args.debug:
54 | print(self.rpcs)
55 | print(
56 | "{} not in : {}".format(
57 | self.loops_indexes[i],
58 | self.loops_indexes[i] not in self.rpcs,
59 | )
60 | )
61 | if self.loops_indexes[i] not in self.rpcs:
62 | self.rpcs[self.loops_indexes[i]] = Presence(client_id)
63 | self.try_connect(self.loops_indexes[i])
64 |
65 | func(self, self.loops_indexes[i], computer)
66 | loop += 1
67 | except ConnectionResetError:
68 | self.try_connect(self.loops_indexes[i])
69 | except KeyboardInterrupt:
70 | print("Closing connection.")
71 | sys.exit(0)
72 |
73 | def try_connect(self, key: str):
74 | while True:
75 | try:
76 | if args.debug:
77 | print('try_connect(key="{}") on {}'.format(key, self.rpcs[key]))
78 | self.rpcs[key].connect()
79 | break
80 | except ConnectionRefusedError:
81 | print(
82 | "RPC connection refused (is Discord open?); trying again in 30 seconds"
83 | )
84 | time.sleep(30)
85 |
86 | def try_clear(self, key: str):
87 | # Pypresence clear doesn't work anymore
88 | # try:
89 | # if args.debug:
90 | # print(
91 | # "[key={}] try_clear(pid={} on {}".format(
92 | # key, os.getpid(), self.rpcs[key]
93 | # )
94 | # )
95 | # self.rpcs[key].clear(pid=os.getpid())
96 | # except exceptions.InvalidID:
97 | # pass
98 | # except exceptions.ServerError as e:
99 | # print(e)
100 | # pass
101 | self.rpcs[key].close()
102 |
103 | def try_update(
104 | self,
105 | key: str,
106 | state,
107 | details,
108 | large_image,
109 | large_text,
110 | small_image,
111 | small_text,
112 | start,
113 | ):
114 | try:
115 | if args.debug:
116 | print('try_update(key="{}") on {}'.format(key, self.rpcs[key]))
117 | self.rpcs[key].update(
118 | state=state,
119 | details=details,
120 | large_image=large_image,
121 | large_text=large_text,
122 | small_image=small_image,
123 | small_text=small_text,
124 | start=start,
125 | )
126 | # ConnectionResetError is here to avoid crashing if Discord is still just starting
127 | except (ConnectionResetError, exceptions.InvalidID):
128 | pass
--------------------------------------------------------------------------------
/fetch_cord/update.py:
--------------------------------------------------------------------------------
1 | #from __future__ import annotations
2 |
3 | import urllib.request, sys, os
4 | from .args import parse_args
5 |
6 | args = parse_args()
7 |
8 | def update():
9 | print("Updating database...")
10 | url = f"https://raw.githubusercontent.com/MrPotatoBobx/FetchCord/{'testing' if args.testing else 'master'}/fetch_cord/resources/fetchcord_ids.json"
11 | urllib.request.urlretrieve(
12 | url, os.path.dirname(__file__) + "/resources/fetchcord_ids.json"
13 | )
14 | sys.exit(0)
15 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | from os.path import dirname, join
3 | import setuptools
4 | import fetch_cord.__init__ as __init__
5 |
6 | setuptools.setup(
7 | name="FetchCord",
8 | version=__init__.VERSION,
9 | description="grabs information about your Distro and displays it as Discord Rich Presence.",
10 | long_description=open(join(dirname(__file__), "README.md")).read(),
11 | long_description_content_type="text/markdown",
12 | url="https://github.com/MrPotatoBobx/FetchCord",
13 | author="MrPotatoBobx",
14 | author_email="junkahole23@protonmail.com",
15 | license="MIT",
16 | package_data={
17 | "fetch_cord": [
18 | "config_schema.json",
19 | "resources/default.conf",
20 | "resources/fetch_cord.conf",
21 | "resources/fetchcord_ids.json",
22 | "computer/*.py",
23 | "computer/*/*.py",
24 | ]
25 | },
26 | packages=["fetch_cord"],
27 | include_package_data=True,
28 | install_requires=["pypresence", "psutil", "importlib-resources"],
29 | keywords=["distro", "info", "discord", "fetch"],
30 | classifiers=[
31 | "License :: OSI Approved :: MIT License",
32 | "Programming Language :: Python :: 3",
33 | "Operating System :: OS Independent",
34 | ],
35 | python_requires=">=3.6",
36 | entry_points={
37 | "console_scripts": [
38 | "fetchcord=fetch_cord.__main__:main",
39 | ]
40 | },
41 | )
42 |
--------------------------------------------------------------------------------
/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: fetchcord
2 | version: git # By specifying git for the version, the current git tag or commit will be used as the version string. Versions carry no semantic meaning in snaps. This can be changed to a normal version number if desired.
3 | summary: FetchCord
4 | grade: stable
5 | description: |
6 | FetchCord grabs your OS info and displays it as Discord Rich Presence
7 | base: core18
8 | confinement: classic
9 |
10 | parts:
11 | fetchcord:
12 | plugin: python
13 | python-version: python3
14 | source: .
15 | stage-packages:
16 | - neofetch
17 | python-packages:
18 | - pypresence
19 | - psutil
20 | - importlib-resources
21 |
22 | apps:
23 | fetchcord:
24 | command: bin/fetchcord
--------------------------------------------------------------------------------
/systemd/fetchcord.service:
--------------------------------------------------------------------------------
1 | # Please use 'systemctl --user edit fetchcord' to change 'ExecStart' when adding arguments!
2 | # The following is a simple example of the override:
3 |
4 | # [Service]
5 | # ExecStart=
6 | # ExecStart=-/usr/bin/fetchcord --nohost --time 15 --terminal 'gnome-terminal' --termfont 'Terminus Medium'
7 |
8 | [Unit]
9 | Description=Display OS info as Discord Rich Presence
10 | Documentation=https://github.com/MrPotatoBobx/FetchCord
11 | After=network.target multi-user.target graphical-session.target
12 |
13 | [Service]
14 | Environment=PYTHONUNBUFFERED=1
15 | ExecStart=-/usr/bin/env fetchcord
16 | Restart=always
17 | RestartSec=10
18 |
19 | [Install]
20 | WantedBy=default.target
21 |
--------------------------------------------------------------------------------
/tests/test_fetch_cord_computer.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from fetch_cord.computer.Computer import Computer
4 |
5 |
6 | def make_orderer():
7 | order = {}
8 |
9 | def ordered(f):
10 | order[f.__name__] = len(order)
11 | return f
12 |
13 | def compare(a, b):
14 | return [1, -1][order[a] < order[b]]
15 |
16 | return ordered, compare
17 |
18 |
19 | ordered, compare = make_orderer()
20 | unittest.defaultTestLoader.sortTestMethodsUsing = compare
21 |
22 |
23 | class TestFetchCordComputer(unittest.TestCase):
24 | """Test class for Computer module"""
25 |
26 | pc: Computer
27 |
28 | @classmethod
29 | def setUpClass(cls):
30 | """Setup the Computer class and load the neofetch info"""
31 |
32 | cls.pc = Computer()
33 |
34 | @classmethod
35 | def tearDownClass(self):
36 | """Called once at the end"""
37 | pass
38 |
39 | @ordered
40 | def test_detected_os(self):
41 | """Test the detected os result"""
42 |
43 | print("Detected OS : " + self.pc.os)
44 |
45 | @ordered
46 | def test_detected_neofetch(self):
47 | """Test detected neofetch"""
48 |
49 | print("Detected Neofetch : ", end="")
50 | if self.pc.neofetch:
51 | print("neofetch")
52 | elif self.pc.neofetchwin:
53 | print("neofetch-win")
54 | else:
55 | print("None")
56 |
57 | @ordered
58 | def test_detected_cpu(self):
59 | """Test detected CPU"""
60 |
61 | if len(self.pc.cpu) == 0 or self.pc.cpu == ["N/A"]:
62 | print("No CPU detected !")
63 | else:
64 | for cpu in self.pc.cpu:
65 | print("Detected CPU : " + cpu.model)
66 | print("Detected CPU Temp : " + str(cpu.temp) + "°c")
67 |
68 | @ordered
69 | def test_detected_gpu(self):
70 | """Test detected GPU"""
71 |
72 | if len(self.pc.gpu) == 0 or self.pc.gpu == ["N/A"]:
73 | print("No GPU detected !")
74 | else:
75 | for gpu in self.pc.gpu:
76 | print("Detected GPU : " + gpu.model)
77 |
78 | @ordered
79 | def test_detected_disks(self):
80 | """Test detected disks"""
81 |
82 | if len(self.pc.disks) == 0 or self.pc.disks == ["N/A"]:
83 | print("No Disk detected !")
84 | else:
85 | for disk in self.pc.disks:
86 | print("Detected Disk : " + disk)
87 |
88 | @ordered
89 | def test_detected_memory(self):
90 | """Test detected memory"""
91 |
92 | print("Detected Memory : " + "\t".join(self.pc.memory))
93 |
94 | @ordered
95 | def test_detected_osinfo(self):
96 | """Test detected OS info"""
97 |
98 | print("Detected OS info : " + "\t".join(self.pc.osinfo))
99 |
100 | @ordered
101 | def test_detected_motherboard(self):
102 | """Test detected motherboard"""
103 |
104 | print("Detected Motherboard : " + "\t".join(self.pc.motherboard))
105 |
106 | @ordered
107 | def test_detected_host(self):
108 | """Test detected host"""
109 |
110 | print("Detected host : " + "\t".join(self.pc.host))
111 |
112 | @ordered
113 | def test_detected_resolution(self):
114 | """Test detected resolution"""
115 |
116 | print("Detected resolution : " + "\t".join(self.pc.resolution))
117 |
118 | @ordered
119 | def test_detected_theme(self):
120 | """Test detected theme"""
121 |
122 | print("Detected theme : " + "\t".join(self.pc.theme))
123 |
124 | @ordered
125 | def test_detected_packages(self):
126 | """Test detected packages"""
127 |
128 | print("Detected packages : " + "\t".join(self.pc.packages))
129 |
130 | @ordered
131 | def test_detected_shell(self):
132 | """Test detected shell"""
133 |
134 | print("Detected shell : " + "\t".join(self.pc.shell))
135 |
136 | @ordered
137 | def test_detected_kernel(self):
138 | """Test detected kernel"""
139 |
140 | print("Detected kernel : " + "\t".join(self.pc.kernel))
141 |
142 | @ordered
143 | def test_detected_terminal(self):
144 | """Test detected terminal"""
145 |
146 | print("Detected terminal : " + "\t".join(self.pc.terminal))
147 |
148 | @ordered
149 | def test_detected_font(self):
150 | """Test detected font"""
151 |
152 | print("Detected font : " + "\t".join(self.pc.font))
153 |
154 | @ordered
155 | def test_detected_de(self):
156 | """Test detected de"""
157 |
158 | print("Detected de : " + "\t".join(self.pc.de))
159 |
160 | @ordered
161 | def test_detected_wm(self):
162 | """Test detected wm"""
163 |
164 | print("Detected wm : " + "\t".join(self.pc.wm))
165 |
166 |
167 | if __name__ == "__main__":
168 | unittest.main()
169 |
--------------------------------------------------------------------------------