"""Functions related to setting the wallpaper.""" from pathlib import Path from os import makedirs, remove from downloader_cli.download import Download from simber import Logger from QuickWall.blacklist import Blacklist from QuickWall.wal import Wal # Declare the logger logger = Logger("SetPaper") class SetPaper: """ Download the wallpaper and set it using nitrogen. """ def __init__( self, entity_list, setter, passed_dir="~/.cache/QuickWall", disable_blacklist=False, disable_theme=False ): self.entity_list = entity_list self._dir_path = Path(passed_dir).expanduser() self._exists() makedirs(self._dir_path, exist_ok=True) self.setter_type = setter # Update by calling the following function
PictureType) from mutagen.mp3 import MP3 from mutagen.mp4 import MP4, MP4Cover from mutagen import File from mutagen.flac import Picture from base64 import b64encode import requests import os from rich.prompt import Prompt from ytmdl import prepend, defaults from simber import Logger from ytmdl.meta import preconfig # import traceback logger = Logger("song") # ----------------------cover-------------------- def dwCover(song): """Download the song cover img from itunes.""" # Try to download the cover art as cover.jpg in temp logger.info("Preparing the album cover") try: imgURL = song.artwork_url_100 # Check if the passed imgURL is a local file # this is possible if the metadata was entered manually. imgURL = os.path.expanduser(imgURL) if os.path.exists(imgURL):
# values that specifies wich API providers to use for getting # the song metadata. Available values right now are: # "{{supported_providers}}". # Please check the github page of ytmdl for more information. # #METADATA_PROVIDERS = "itunes, gaana" # #*****************************************# # The DEFAULT_FORMAT denotes what to use as default for downloading. # Available values are: # "{{supported_formats}}" # #DEFAULT_FORMAT = "mp3" #''' logger = Logger("config") class DEFAULTS: """Some default stuff defined.""" def __init__(self): # The home dir self.HOME_DIR = os.path.expanduser('~') # The default song dir self.SONG_DIR = self._get_music_dir() # The temp dir self.SONG_TEMP_DIR = os.path.join(self.SONG_DIR, 'ytmdl') # The default song quality
"""All utility related functions defined here""" import subprocess from pathlib import Path from shutil import rmtree from os import mkdir, path, environ from sys import platform from distutils.dir_util import copy_tree from simber import Logger # Declare logger logger = Logger("Utility") def is_nitrogen(): """ Check if nitrogen is present or not """ command = "nitrogen --help" p = subprocess.Popen(command.split(' '), stdout=subprocess.PIPE) ret, err = p.communicate() return True if err is None else False def is_feh(): """ Check if feh is installed. """
"""Handle inserting metadata manually.""" from datetime import datetime from simber import Logger from re import sub, match logger = Logger("manual") class Meta: """ Meta Class will have properties same as those of Gaana and Itunes in order to make them compatible with the other modules that are using this data to write to the song files. Following properties will only be present release_date : Date of Release of the song track_name : Name of the song artist_name : Name of the artist(s) collection_name : Name of the album primary_genre_name : Genre of the song track_number : Number of the track in the album artwork_url_100 : URL of the album cover """ def __init__(self): self.release_date = "{}T00:00:00Z".format(datetime.now().date()) self.track_name = "N/A" self.artist_name = "N/A"
"""All code related to setting wallpaper in xfce is defined here.""" import os from pathlib import Path from bs4 import BeautifulSoup from simber import Logger logger = Logger("XFCE") class XFCESetter: def __init__(self): self.cmd = "xfconf-query -c xfce4-desktop -p {wallpaper_image} -s {wallpaper}" # Save the value of the previous wallpaper. self._extract_prev_wall() def _extract_prev_wall(self): """Extract the saved wallpaper from the xml file.""" FILE = Path( "~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml" ).expanduser() try: soup = BeautifulSoup(open(FILE, 'r'), features="html.parser") wall = soup.find("property", attrs={"name": "last-image"}) except FileNotFoundError: logger.warning( "{}: Not found. Wallpaper will not be restored!".format(FILE)) return except Exception as e: logger.error( "While extracting the wallpaper, error thrown: {}".format(e))
"""Handle extracting the issues Extract all the comments from the issues in the given repo and accordingly return the messages. """ from requests import Session, get from simber import Logger from repostatus.url_handler import URLHandler, update_header_token from repostatus import Default from typing import List, Dict logger = Logger("issue") def _get_comments_each(comment_url: str, token: Dict = None) -> List: """Get the comments from the passed URL and return a list containing those. Each issue has some comments excluding the one added when the issue was created. """ access_token = Default.token_header if token is None else token response = get(comment_url, headers=access_token) comments = [] if response.status_code != 200 or not len(response.json()): return comments comments = [comment["body"] for comment in response.json()]
"""Handle requests related to repo. Everything related to the repo like getting details etc will be handled through this module. """ from pydantic import BaseModel from requests import get from typing import List, Optional, Dict from fastapi import HTTPException, APIRouter, Header from simber import Logger from repostatus import Default router = APIRouter() logger = Logger("repo_handler") class Repo(BaseModel): name: str full_name: str language: str = None stars: int url: str def get_repo_list(username: str, headers: Dict) -> List: """Get the list of public repos for the username passed. Use the official GitHub API with the access token
open_archive_stream, is_present_in_archive, add_song_to_archive ) from ytmdl.utils.ytdl import is_ytdl_config_present from ytmdl.yt import is_yt_url from ytmdl.__version__ import __version__ # init colorama for windows init() LOGGER_OUTTEMPLATE = " %a{}==>{}%".format(Style.BRIGHT, Style.RESET_ALL) LOGGER_FILEFORMAT = "[{logger}]:[{time}]: " logger = Logger('ytmdl', log_path=path.join(xdg_cache_home, 'ytmdl/logs/log.cat'), format=LOGGER_OUTTEMPLATE, file_format=LOGGER_FILEFORMAT, update_all=True ) def arguments(): """Parse the arguments.""" parser = argparse.ArgumentParser() parser.add_argument('SONG_NAME', help="Name of the song to download.\ Can be an URL to a playlist as well. It will be\ automatically recognized.", type=str, nargs="*") parser.add_argument('-q', '--quiet', help="Don't ask the user to select songs\ if more than one search result.\
"""Set the theme extracted from the wallpaper.""" from pywal import ( colors, export, sequences, theme, settings ) import os from simber import Logger logger = Logger("wal") class Wal: """Change the theme based on the passed wallpaper""" def set(self, wallpaper): logger.debug("{}".format(wallpaper)) self.colors_plain = colors.get(wallpaper) sequences.send(self.colors_plain, to_send=True) colors.palette() def save(self): export.every(self.colors_plain) def restore(self): self.colors_plain = theme.file(os.path.join( settings.CACHE_DIR, "colors.json" )) sequences.send(self.colors_plain, to_send=True)
"""Handle the callback router that will help with completion of the oauth. """ from fastapi import APIRouter, HTTPException, Query from fastapi.responses import HTMLResponse from pymongo import MongoClient from simber import Logger from requests import post from config import get_settings from assets.html import get_html logger = Logger("callback_handler", level="DEBUG") router = APIRouter() REPOSTATUSDB_URI = get_settings().repostatusdb_uri client = MongoClient(REPOSTATUSDB_URI) db = client.repostatus def is_state_present(state: str) -> bool: """Check if the state is present in the database.""" match = db.sessionstate.find_one({"state": state}) return True if match else False def exchange_token(code: str, state: str) -> str: """Use the code provided and get the access token. Return the access token, once fetched.
from pathlib import Path from QuickWall.SetPaper import SetPaper from QuickWall.utility import (is_nitrogen, clear_cache, migrate_to_new_loc) from simber import Logger from QuickWall.setter import WallSetter from QuickWall.wall import Wall from QuickWall.blacklist import Blacklist # Declare the logger LOGGER_OUTTEMPLATE = "%a[{logger}]%" LOGGER_FILEFORMAT = "[{logger}] [{levelname}] [{time}] [{lineno}]" logger = Logger("main", log_path=Path('~/.cache/QuickWall/logs/log.cat').expanduser(), format=LOGGER_OUTTEMPLATE, file_format=LOGGER_FILEFORMAT, update_all=True) def parse(): """Parse the arguments.""" parser = argparse.ArgumentParser(description="QuickWall - Quickly set\ latest wallpapers from Unsplash\ directly from the commandline.", epilog="If you find any bugs, feel\ free to raise an issue in the GitHub\ [https://github.com/deepjyoti30/QuickWall] page." ) parser.add_argument('--version', action='version',
"""Functions related to nitrogen.""" import subprocess from simber import Logger # Declare logger logger = Logger("nitrogen") class nitrogen: """ Class to use nitrogen to set wallpapers. """ def restore(self): """ Restore the wallpaper using nitrogen. """ logger.info("Restoring the last wallpaper...") c = 'nitrogen --restore' subprocess.Popen(c.split(), stdout=subprocess.PIPE) def set(self, file_path): """ Set the wallpaper temporaririly """ c = 'nitrogen --set-zoom-fill {}'.format(file_path) p = subprocess.Popen(c.split(' '), stdout=subprocess.PIPE) ret, err = p.communicate() def set_perm(self, file_path):
"""Handle getting list of repositories and commits and messages. Fetches a list of repos and commits along with, its messages Author:Vedant Baviskar Date: 27/10/2020 """ from requests import Session from repostatus.url_handler import URLHandler, update_header_token from typing import List from simber import Logger logger = Logger("commits") def get_commit(commit_url: str, token: str = None) -> List: """Use api to return the commits and the messages.""" commits_request = URLHandler(commit_url).commit_request commits = [] if token: update_header_token(commits_request, token) # We need to make the same request 5 times in order to # get 500 commit messages for request_number in range(5): commits_request.url += "&page={}".format(request_number + 1) response = Session().send(commits_request)
""" Handle the archive related feature. """ from pathlib import Path from typing import List, Union from simber import Logger from io import TextIOWrapper from ytmdl.yt import extract_video_id # Create logger logger = Logger("archive") def open_archive_stream(file: str) -> Union[List, TextIOWrapper]: """ Read the archive file and extract all the videoId's passed. This file will be read as text and should contain videoId's in each line. """ file_path: Path = Path(file).expanduser() # Check if the file exists if not file_path.exists(): logger.critical("Passed archive file does not exist. Exiting!") stream: TextIOWrapper = file_path.open("r+") file_content: List = stream.read().split("\n") return file_content, stream
"""All blacklist related functions.""" from pathlib import Path from simber import Logger # Declare logger logger = Logger("blacklist") class Blacklist: """ Functions to be used related to blacklist. """ def __init__(self, unique_id): self.blacklist_path = Path('~/.cache/QuickWall/blacklist').expanduser() self.unique_id = unique_id def is_blacklisted(self): """ Check if the passed unique_id is available in the blacklist. """ if not self.blacklist_path.exists(): return False blacklist = open(self.blacklist_path).read().split('\n')[1:] logger.debug(str(blacklist)) if self.unique_id in blacklist:
"""Set wallpapers in KDE.""" import dbus from os import path, system from shutil import copy from simber import Logger logger = Logger("KDE") def setwallpaper(filepath): """ This script is taken from https://github.com/pashazz/ksetwallpaper/ All the credit goes to the user for the code, I'm just using it to add a functionality to my app. """ jscript = """var allDesktops = desktops(); for ( i = 0; i < allDesktops.length;i++ ) { d = allDesktops[i]; d.wallpaperPlugin = "org.kde.image"; d.currentConfigGroup = Array("Wallpaper", "org.kde.image", "General"); d.writeConfig("Image", "file://%s") } """ bus = dbus.SessionBus() plasma = dbus.Interface(bus.get_object('org.kde.plasmashell', '/PlasmaShell'), dbus_interface='org.kde.PlasmaShell') plasma.evaluateScript(jscript % filepath)
import subprocess from pathlib import Path from simber import Logger logger = Logger("GNOME") class GNOMESetter: def __init__(self): self.cmd = "gsettings set org.gnome.desktop.background picture-uri file://{wallpaper}" self._extract_prev_wall() def _extract_prev_wall(self): """Extract the saved wallpaper from the cmd line.""" self.SAVED_WALL = subprocess.check_output(["gsettings", "get", "org.gnome.desktop.background", "picture-uri"])[1:-2].decode('utf-8') def set(self, wallpaper): """Set the wallpaper temporarily.""" subprocess.call(self.cmd.format(wallpaper=wallpaper).split(" ")) def set_perm(self, wallpaper): """Set the wallpaper permanently.""" self.set(wallpaper) def restore(self): """Restore the saved wallpaper.""" self.set_perm(self.SAVED_WALL)
"""Setter related functions.""" from QuickWall.nitrogen import nitrogen from QuickWall.feh import feh from QuickWall.kde import KDEsetpaper from QuickWall.xfce import XFCESetter from QuickWall.gnome import GNOMESetter from simber import Logger from QuickWall.utility import get_desktop_environment # Declare the logger logger = Logger("Setter") LockscreenCompatibleSetters = ["kde"] class WallSetter: """ Select the wallpaper setter. """ def __init__(self, setter_type, lockscreen=False): self.setter_type = setter_type self.available_setters = { 'nitrogen': nitrogen, 'feh': feh, 'kde': KDEsetpaper, 'xfce': XFCESetter, 'gnome': GNOMESetter, } self.setter = None self._select_setter()
import requests from re import sub from simber import Logger logger = Logger('Wall') class Wall: """ Class to do tasks like downloading the wallpaper. URL list has 4 entries: desc: Description of the image name: Name of the user who uploaded the image dw_link: Download link of the image unique_id: ID to save the image """ def __init__(self, photo_id, random=None, search=None): self.s_term = None self._acces_key = "15bcea145de0b041ec8d3b16bf805e232c83cf52d569a06708aa51f33a4f14f4" self._URL = "https://api.unsplash.com/photos/" self._URL_list = [] self.random = random self.search = search self.id = photo_id self._build_URL() def _build_URL(self): """Build the URL based on the passed args."""
"""Contain all the core functions for ytmdl""" from typing import Union from simber import Logger from colorama import Fore, Style from ytmdl import (yt, song, stringutils, defaults, utility, manual, metadata) from ytmdl.exceptions import (DownloadError, ConvertError, NoMetaError, MetadataError) logger = Logger("core") def search(song_name, args) -> Union[str, str]: """Search the song on YouTube, ask the user for an input and accordingly return a selected song. The song can be extracted either from an URL or the name. If the name is present, we will search on YouTube for the name, ask the user for a choice and accordingly return the choice. If the URL is present, we will extract the data from the URL and return it accordingly. """ # Declare some default values YOUTUBE_LINK_BASE = "https://youtube.com{}" PASSED_CHOICE = args.choice URL = args.url IS_QUIET = args.quiet if URL is None:
Nishan Pantha(c) 2017-18 [email protected] """ from glob import glob import os from ytmdl.stringutils import (remove_multiple_spaces, remove_punct, compute_jaccard, remove_stopwords, check_keywords) from ytmdl.defaults import DEFAULT from ytmdl.prepend import PREPEND from simber import Logger from colorama import Fore, Style logger = Logger("cache") class Cache: """The main caching component.""" def __init__(self, directory=None): """Init the stuff.""" if directory is None: directory = DEFAULT.SONG_DIR # Check the dir only if special characters are present if '$' in directory: directory = directory.split("$")[0] directory = os.path.expanduser(directory) self.directory = directory self.max_depth = 4
"""Functions related to usign feh as wallpaper setter.""" import subprocess from pathlib import Path from simber import Logger # Declare the logger logger = Logger("feh") class feh: def __init__(self): self.feh_config_path = Path('~/.fehbg').expanduser() # Verify feh exists self.__verify_feh_bg_exists() self.current = self._find_current() def __verify_feh_bg_exists(self): """ If feh is not run with `feh --bg-fill` even once before then the .fehbg file will not be present. Make a check to see if the file is present, and if not then raise an error asking the user to run it once. """ if not self.feh_config_path.exists(): logger.critical( ".fehbg does not exist. Seems like feh was never used before. Run feh using `feh --bg-fill <wallpaper_file>` and try again."
""" Handle the stuff related to trimming the song in order to remove the speech. """ from inaSpeechSegmenter import Segmenter from warnings import filterwarnings from os import environ, remove, rename import ffmpeg from simber import Logger # Setup the logger name logger = Logger("Trimmer") # Remove the warnings from tensorflow environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # Ignore warnings filterwarnings("ignore") class Trim: """ Class that will handle the processing of the files. filename: File that we want to process. We will run the speech segmenter on it and get the music timestamps. Once we have the stamps, we can just trim the music part from the song and keep the name same. """ def __init__(self, filename):
"""Handle creation of the URL's""" from re import match from simber import Logger from requests.models import PreparedRequest from requests import Request from repostatus import Default logger = Logger("url_handler") class URLHandler(object): """Handle dynamic creation of URL's for the GitHub API. The URL's will be created based on the necessity of the request. """ def __init__(self, repo: str) -> None: self.repo = self._verify_repo(repo) self._BASE_URL = "https://api.github.com/" self._HEADERS = { 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'repostatus', 'Authorization': 'Basic {}'.format(Default.basic_token) } self._type_map = { 'issue': { 'url': 'repos/{}/issues', 'params': {} }, 'pull': {
"""Define functions related to getting tags.""" import itunespy import re from ytmdl.stringutils import (remove_multiple_spaces, remove_punct, compute_jaccard, remove_stopwords, check_keywords) from ytmdl import defaults from simber import Logger from ytmdl.meta import gaana, deezer, saavn, lastfm, musicbrainz, preconfig from unidecode import unidecode logger = Logger('metadata') def _logger_provider_error(exception, name): """Show error if providers throw an error""" logger.debug('{}'.format(exception)) logger.error("Something went wrong with {}. The program will continue with" "the other providers. Please check '{}' for more details.\ ".format(name, logger.get_log_file())) def get_from_itunes(SONG_NAME): """Try to download the metadata using itunespy.""" # Try to get the song data from itunes try: SONG_INFO = itunespy.search_track(SONG_NAME) return SONG_INFO except Exception as e: _logger_provider_error(e, 'iTunes')
""" Handle all the util functions for working with YouTube Music. """ from ytmusicapi import YTMusic from simber import Logger from ytmdl.exceptions import ExtractError # Create logger logger = Logger("ytmusic") def get_title_from_ytmusic(videoId: str) -> str: """ Get the title of the song from the videoID. Youtube actually supports Youtube videoId's that can be found in YouTube Music with the proper song title. This is way more effective and correct than extracting the title from the YouTube video. """ ytmusic = YTMusic() details = ytmusic.get_song(videoId=videoId) # Check if error occured if details["playabilityStatus"]["status"] != "OK": raise ExtractError(videoId)
"""Definition of functions that are used to interact with youtube.""" import requests import os import youtube_dl from youtube_dl.utils import DownloadError from re import match from ytmdl import defaults, utility, stringutils from downloader_cli.download import Download import traceback from sys import stdout from youtube_search import YoutubeSearch from simber import Logger from ytmdl.exceptions import ExtractError logger = Logger("yt") def get_youtube_streams(url): """Get both audio & video stream urls for youtube using youtube-dl. PS: I don't know how youtube-dl does the magic """ cli = "youtube-dl -g {}".format(url) output, error = utility.exe(cli) stream_urls = output.split("\n") url = stream_urls[1] return url
"""All directory handling definitions.""" import os import glob import shutil from html import unescape from re import sub from ytmdl import defaults from simber import Logger logger = Logger("Dir") def __replace_special_characters(passed_name: str) -> str: """ In the passed name, replace the special characters like / with a `-` so that it does not raise any errors related to the OS while moving the file """ # TODO: Also add support for removing backslash return sub(r'/', '-', passed_name) def cleanup(TRACK_INFO, index, datatype, remove_cached=True): """Move the song from temp to the song dir.""" try: SONG = glob.glob( os.path.join(defaults.DEFAULT.SONG_TEMP_DIR, '*{}'.format(datatype))) SONG = SONG[0]
"""Handle the package as a whole. This should be the entrypoint for everyone accessing this package to get the happiness status. """ from textblob import TextBlob from repostatus.filter import filter from repostatus.issues import get_issue_comments from repostatus.pulls import get_pull_comments from repostatus.message import get_commit from simber import Logger from requests import Session from typing import List, Dict from repostatus.url_handler import URLHandler, update_header_token logger = Logger("happiness") class HappinessContainer(object): """Contain the happiness related data in a nice manner so that it's easier to access """ def __init__(self, data: List = [], polarity: float = None) -> None: self.__data = data self.__polarity = polarity self.__emotion = self.__map_emotions(polarity) self.__data_compiled = None self.__color_emotion_map = { "angry": { "hex": "#F44336", "name": "red"