a
This commit is contained in:
parent
eb2bcf4101
commit
02e78096ab
|
@ -6,6 +6,7 @@ from .. import dbus
|
|||
from .. import __version__ as version
|
||||
from ..config import var
|
||||
from ..database import db
|
||||
from ..exceptions import AccountNotFoundError, NoAccountsError
|
||||
|
||||
|
||||
class Application(Gtk.Application):
|
||||
|
@ -28,6 +29,75 @@ class Application(Gtk.Application):
|
|||
self.connect('startup', self.handle_startup)
|
||||
|
||||
|
||||
def create_tabs(self):
|
||||
with db.session as s:
|
||||
for row in s.fetch('tabs', orderby='order'):
|
||||
self.window.new_tab(row=row)
|
||||
|
||||
for url in self.startup_urls:
|
||||
self.window.new_tab(url, switch=row.active)
|
||||
|
||||
if len(self.window.tabdata.keys()) < 1:
|
||||
self.window.new_tab(None, switch=False)
|
||||
|
||||
self.window.startup = False
|
||||
|
||||
|
||||
def get_account_by_handle(self, username, domain=None):
|
||||
if not len(self.accounts):
|
||||
raise NoAccountsError('No accounts')
|
||||
|
||||
for acct in self.accounts:
|
||||
if not domain and username == acct.handle:
|
||||
return acct
|
||||
|
||||
elif domain and username == acct.handle and domain == acct.domain:
|
||||
return acct
|
||||
|
||||
raise AccountNotFoundError('Cannot find account')
|
||||
|
||||
|
||||
def get_account_by_id(self, id):
|
||||
if not len(self.accounts):
|
||||
raise NoAccountsError('No accounts')
|
||||
|
||||
for acct in self.accounts:
|
||||
if acct.id == id:
|
||||
return acct
|
||||
|
||||
raise AccountNotFoundError('Cannot find account')
|
||||
|
||||
|
||||
def get_default_account(self):
|
||||
if not len(self.accounts):
|
||||
raise NoAccountsError('No accounts')
|
||||
|
||||
with db.session as s:
|
||||
default = s.get_config('active_acct')
|
||||
|
||||
for acct in self.accounts:
|
||||
if default == acct.id:
|
||||
return acct
|
||||
|
||||
s.put_config('active_acct', self.accounts[0].id)
|
||||
|
||||
return self.accounts[0]
|
||||
|
||||
|
||||
def set_clipboard_text(self, *text):
|
||||
self.clipboard.set_text(' '.join(text), -1)
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
db.unregister_all_callbacks()
|
||||
|
||||
if self.window:
|
||||
#self.window.passwords.db.disconnect()
|
||||
self.window.handle_window_close()
|
||||
|
||||
super().quit()
|
||||
|
||||
|
||||
def handle_activate(self, *args):
|
||||
self.window = Window(self)
|
||||
self.dbus = dbus.Server(self.window)
|
||||
|
@ -37,6 +107,12 @@ class Application(Gtk.Application):
|
|||
self.window.show()
|
||||
|
||||
|
||||
def handle_clipboard_clear_password(self, password):
|
||||
if self.clipboard.wait_for_text() == password:
|
||||
logging.debug('Clear clipboard text')
|
||||
self.clipboard.set_text('', 0)
|
||||
|
||||
|
||||
def handle_startup(self, *args):
|
||||
Gtk.Application.do_startup(self)
|
||||
accel = Gio.SimpleAction.new('accel', GLib.VariantType.new('s'))
|
||||
|
@ -82,79 +158,6 @@ class Application(Gtk.Application):
|
|||
self.accounts = s.fetch('accounts').all()
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
db.unregister_all_callbacks()
|
||||
|
||||
if self.window:
|
||||
#self.window.passwords.db.disconnect()
|
||||
self.window.handle_window_close()
|
||||
|
||||
super().quit()
|
||||
|
||||
|
||||
def create_tabs(self):
|
||||
with db.session as s:
|
||||
for row in s.fetch('tabs', orderby='order'):
|
||||
self.window.new_tab(row=row)
|
||||
|
||||
for url in self.startup_urls:
|
||||
self.window.new_tab(url, switch=row.active)
|
||||
|
||||
if len(self.window.tabdata.keys()) < 1:
|
||||
self.window.new_tab(None, switch=False)
|
||||
|
||||
self.window.startup = False
|
||||
|
||||
|
||||
def get_account_by_handle(self, username, domain=None):
|
||||
if not len(self.accounts):
|
||||
raise IndexError('No accounts')
|
||||
|
||||
for acct in self.accounts:
|
||||
if not domain and username == acct.handle:
|
||||
return acct
|
||||
|
||||
elif domain and username == acct.handle and domain == acct.domain:
|
||||
return acct
|
||||
|
||||
raise IndexError('Cannot find account')
|
||||
|
||||
|
||||
def get_account_by_id(self, id):
|
||||
if not len(self.accounts):
|
||||
raise IndexError('No accounts')
|
||||
|
||||
for acct in self.accounts:
|
||||
if acct.id == id:
|
||||
return acct
|
||||
|
||||
raise IndexError('Cannot find account')
|
||||
|
||||
|
||||
def get_default_account(self):
|
||||
if not len(self.accounts):
|
||||
raise IndexError('No accounts')
|
||||
|
||||
with db.session as s:
|
||||
default = s.get_config('active_acct')
|
||||
|
||||
for acct in self.accounts:
|
||||
if default == acct.id:
|
||||
return acct
|
||||
|
||||
return self.accounts[0]
|
||||
|
||||
|
||||
def set_clipboard_text(self, *text):
|
||||
self.clipboard.set_text(' '.join(text), -1)
|
||||
|
||||
|
||||
def handle_clipboard_clear_password(self, password):
|
||||
if self.clipboard.wait_for_text() == password:
|
||||
logging.debug('Clear clipboard text')
|
||||
self.clipboard.clear()
|
||||
|
||||
|
||||
def handle_accel(self, signal, action):
|
||||
action = action.get_string()
|
||||
tab = self.window.active_tab
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from .. import fediverse
|
||||
from ..database import db, default_permissions
|
||||
from ..exceptions import AccountNotFoundError, NoAccountsError
|
||||
from ..functions import SignalBlock, connect, get_buffer_text
|
||||
from ..objects.login_rows import SavedLoginRow
|
||||
from ..passwords import passdb
|
||||
|
@ -8,12 +9,13 @@ from ..passwords import passdb
|
|||
class StatusBar:
|
||||
def __init__(self, window):
|
||||
self.window = window
|
||||
self.app = window.app
|
||||
|
||||
self.siteoptions_handler_ids = []
|
||||
self.bookmark_row = None
|
||||
self.theme_enabled = False
|
||||
|
||||
self.toot_account = {}
|
||||
self.toot_acct = None
|
||||
self.toot_post = None
|
||||
self.toot_max_len = 500
|
||||
|
||||
|
@ -85,10 +87,10 @@ class StatusBar:
|
|||
|
||||
|
||||
def toot_set_account(self):
|
||||
with db.session as s:
|
||||
self.toot_account = s.get_account()
|
||||
try:
|
||||
self.toot_account = self.app.get_default_account()
|
||||
|
||||
if not self.toot_account:
|
||||
except NoAccountsError:
|
||||
self.window.notification('No active fedi accounts', 'error')
|
||||
return False
|
||||
|
||||
|
@ -171,6 +173,7 @@ class StatusBar:
|
|||
#self.window.active_tab.editing_action('select')
|
||||
#self.window.active_tab.editing_action('copy')
|
||||
self.window.notification('Merp!', 'INFO', 0)
|
||||
print(self.window.context.get_cookie_manager().delete_cookies_for_domain(self.window.active_tab.url.domain))
|
||||
|
||||
#if self.window.themes.current_theme:
|
||||
#self.window.themes.UnloadTheme()
|
||||
|
@ -240,21 +243,21 @@ class StatusBar:
|
|||
|
||||
|
||||
def handle_bookmark_button(self, name):
|
||||
if name == 'save':
|
||||
data = self.bookmark_get_data()
|
||||
with db.session as s:
|
||||
if name == 'save':
|
||||
data = self.bookmark_get_data()
|
||||
|
||||
with db.session as s:
|
||||
if self.bookmark_row:
|
||||
data['id'] = self.bookmark_row.id
|
||||
s.update_row(self.bookmark_row, **data)
|
||||
|
||||
s.put_bookmark(**data)
|
||||
else:
|
||||
s.put_bookmark(**data)
|
||||
|
||||
elif name == 'delete':
|
||||
if self.bookmark_row:
|
||||
s.remove_row(self.bookmark_row)
|
||||
elif name == 'delete':
|
||||
if self.bookmark_row:
|
||||
s.remove_row(self.bookmark_row)
|
||||
|
||||
self.window['statusbar-bookmark-popover'].popdown()
|
||||
self.window.bookmarks.table.refresh()
|
||||
|
||||
|
||||
def handle_fedi_button(self, name):
|
||||
|
@ -346,7 +349,7 @@ class StatusBar:
|
|||
for child in login_list.get_children():
|
||||
child.destroy()
|
||||
|
||||
for row in passdb.fetch(domain=self.window.active_tab.url.domain):
|
||||
for row in passdb.fetch(domain=self.window.active_tab.url.hostname()):
|
||||
login_list.add(SavedLoginRow(row, self.window.active_tab.url)['container'])
|
||||
|
||||
|
||||
|
|
|
@ -282,6 +282,11 @@ default_settings = {
|
|||
'name': 'Serif font',
|
||||
'description': 'Font to use when the page does not specify a font for pictograph fonts'
|
||||
},
|
||||
'user-agent': {
|
||||
'default': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0',
|
||||
'name': 'User Agent',
|
||||
'description': 'How the browser identifies itself when connecting to web servers'
|
||||
},
|
||||
'zoom-text-only': {
|
||||
'default': False,
|
||||
'name': 'Only zoom text',
|
||||
|
@ -302,7 +307,7 @@ class WebSettings(WebKit2.Settings):
|
|||
super().__init__()
|
||||
self.tab = tab
|
||||
|
||||
self.set_user_agent_with_application_details('pyWeb', version)
|
||||
#self.set_user_agent_with_application_details('pyWeb', version)
|
||||
|
||||
for k,v in default_settings.items():
|
||||
self[k] = v['default']
|
||||
|
|
|
@ -88,9 +88,6 @@ var.template.update_env({
|
|||
|
||||
logging.set_config('level', var.loglevel)
|
||||
|
||||
if var.loglevel in ['DEBUG', 'VERBOSE']:
|
||||
izzylog.set_config('level', 'VERBOSE')
|
||||
|
||||
sys.path.insert(-1, dirs.extensions)
|
||||
|
||||
if dirs.data.join('database.sqlite3').exists():
|
||||
|
|
|
@ -120,7 +120,7 @@ default_config = {
|
|||
'default_search': ('ddg', 'str'),
|
||||
'detach_inspector': (False, 'bool'),
|
||||
'download_dir': (Path('~/Downloads').expanduser(), 'path'),
|
||||
'enable_autocomplete': (True, 'bool'),
|
||||
'enable_autocomplete': (False, 'bool'),
|
||||
'fullscreen': (False, 'bool'),
|
||||
'homepage': (var.local + '/', 'str'),
|
||||
'https_force': (True, 'bool'),
|
||||
|
@ -334,12 +334,13 @@ class CustomSession(Session):
|
|||
data = DotDict(
|
||||
name = name,
|
||||
url = url,
|
||||
description = description,
|
||||
category = category or 'Misc',
|
||||
lastupdate = datetime.now()
|
||||
|
||||
)
|
||||
|
||||
if description:
|
||||
data['description'] = description
|
||||
|
||||
return self.insert('bookmarks', **data)
|
||||
|
||||
|
||||
|
|
|
@ -38,11 +38,6 @@ class Search(Row):
|
|||
class Account(Row):
|
||||
_api = None
|
||||
_emojis = None
|
||||
_db = None
|
||||
|
||||
|
||||
def __run__(self, session):
|
||||
self._db = session.db
|
||||
|
||||
|
||||
@property
|
||||
|
@ -53,6 +48,12 @@ class Account(Row):
|
|||
return self._api
|
||||
|
||||
|
||||
@property
|
||||
def active(self):
|
||||
with self._db.session as s:
|
||||
return s.get_config('active_acct') == self.id
|
||||
|
||||
|
||||
@property
|
||||
def avatar(self):
|
||||
return dirs.avatars.join(f'{self.id}.png')
|
||||
|
@ -68,12 +69,6 @@ class Account(Row):
|
|||
return
|
||||
|
||||
|
||||
@property
|
||||
def active(self):
|
||||
with self._db.session as s:
|
||||
return s.get_config('active_acct') == self.id
|
||||
|
||||
|
||||
@property
|
||||
def emojis(self):
|
||||
if not self._emojis:
|
||||
|
@ -186,8 +181,3 @@ class Account(Row):
|
|||
def set_active(self):
|
||||
with self._db.session as s:
|
||||
s.put_config('active_acct', self.id)
|
||||
|
||||
|
||||
def test(self):
|
||||
string = '30+ Transfem Sergal :trans_furr_white: :nbdab: :nbdab:\n\nDoes lots of Python crimes'
|
||||
return self.replace_emojis(string)
|
||||
|
|
5
barkshark_web/exceptions.py
Normal file
5
barkshark_web/exceptions.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
class NoAccountsError(Exception):
|
||||
'Raise when doing an action that requires a fediverse account, but none exist'
|
||||
|
||||
class AccountNotFoundError(Exception):
|
||||
'Raise when a specific account is not found'
|
|
@ -1,38 +1,34 @@
|
|||
// General
|
||||
function connect_event(name, signal, callback) {
|
||||
element = document.getElementById(name);
|
||||
const element = document.getElementById(name);
|
||||
element.addEventListener(signal, callback);
|
||||
}
|
||||
|
||||
|
||||
function delete_item(base_url, id) {
|
||||
request(`${base_url}/${id}`, function(xhr) {
|
||||
if (xhr.status != 200) {return;}
|
||||
request(`${base_url}/${id}`, (response, body) => {
|
||||
if (response.status != 200) {return;}
|
||||
|
||||
var element = document.getElementById(id);
|
||||
const element = document.getElementById(id);
|
||||
element.parentElement.removeChild(element);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function request(url, callback, timeout=5) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.timeout = 5
|
||||
xhr.open('GET', url);
|
||||
|
||||
if (callback != undefined) {
|
||||
xhr.onload = function(event) {
|
||||
callback(event.target);
|
||||
function request(url, callback) {
|
||||
fetch(url).then((response) => {
|
||||
if (callback != null) {
|
||||
response.text().then((body) => {
|
||||
callback(response, body)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function toggle_all_details(class_name, state) {
|
||||
var elements = document.getElementsByClassName(class_name);
|
||||
|
||||
const elements = document.getElementsByClassName(class_name);
|
||||
|
||||
for (let element of elements) {
|
||||
if (state && !element.hasAttribute('open')) {
|
||||
element.setAttribute('open', null);
|
||||
|
@ -44,15 +40,15 @@ function toggle_all_details(class_name, state) {
|
|||
|
||||
|
||||
function toggle_menu() {
|
||||
var menu = document.getElementById('main-menu');
|
||||
var show_text = menu.hasAttribute('show');
|
||||
|
||||
const menu = document.getElementById('main-menu');
|
||||
const show_text = menu.hasAttribute('show');
|
||||
|
||||
if (show_text) {
|
||||
menu.removeAttribute('show');
|
||||
} else {
|
||||
menu.setAttribute('show', null);
|
||||
}
|
||||
|
||||
|
||||
for (let item of document.getElementsByClassName('menu-item-text')) {
|
||||
if (show_text) {
|
||||
item.style.display = 'none'
|
||||
|
@ -71,28 +67,24 @@ function handle_key_enter(event) {
|
|||
|
||||
|
||||
function handle_save_config(event) {
|
||||
var input = event.target;
|
||||
const input = event.target;
|
||||
let value = '';
|
||||
|
||||
if (input.type.toUpperCase() == 'CHECKBOX') {
|
||||
if (input.checked) {
|
||||
var value = 'true';
|
||||
|
||||
value = 'true';
|
||||
} else {
|
||||
var value = 'false';
|
||||
|
||||
value = 'false';
|
||||
}
|
||||
|
||||
} else {
|
||||
var value = input.value;
|
||||
|
||||
value = input.value;
|
||||
}
|
||||
|
||||
const url = new URL(input.form.action);
|
||||
url.searchParams.set(input.id, value)
|
||||
|
||||
request(url, function(xhr) {
|
||||
if (xhr.status == 200) {
|
||||
console.log(xhr.status, url);
|
||||
request(url, (response, body) => {
|
||||
if (response.status == 200) {
|
||||
console.log(`Set config: ${input.id}=${value}`);
|
||||
}
|
||||
});
|
||||
|
@ -102,15 +94,15 @@ function handle_save_config(event) {
|
|||
// Fediverse
|
||||
function create_account_nodes(ids) {
|
||||
for (let id of ids) {
|
||||
request(`/fediverse/acct_info/${id}`, function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
console.log(`Error %{xhr.status} when trying to fetch account: ${xhr.responseText}`);
|
||||
request(`/fediverse/acct_info/${id}`, (response, body) => {
|
||||
if (response.status != 200) {
|
||||
console.log(`Error ${response.status} when trying to fetch account: ${body}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const accts = document.getElementById('accounts');
|
||||
const container = document.createElement('div');
|
||||
container.innerHTML = xhr.responseText;
|
||||
container.innerHTML = body;
|
||||
|
||||
accts.appendChild(container.children[0]);
|
||||
})}
|
||||
|
@ -118,8 +110,8 @@ function create_account_nodes(ids) {
|
|||
|
||||
|
||||
function set_active(acctid) {
|
||||
request(`/fediverse/set_active/${acctid}`, function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
request(`/fediverse/set_active/${acctid}`, (response, body) => {
|
||||
if (response.status != 200) {
|
||||
console.log(`Failed to set account active: ID ${acctid}`);
|
||||
return;
|
||||
}
|
||||
|
@ -127,11 +119,10 @@ function set_active(acctid) {
|
|||
for (let acct of document.getElementsByClassName('account')) {
|
||||
var active = acct.getElementsByClassName('active')[0];
|
||||
|
||||
if (acct.id == `ACCT${acctid}`) {
|
||||
active.style.display = 'none'
|
||||
|
||||
if (acct.id == acctid) {
|
||||
active.style.display = 'none';
|
||||
} else {
|
||||
active.style.display = 'inline-block'
|
||||
active.style.display = 'inline-block';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -140,8 +131,8 @@ function set_active(acctid) {
|
|||
|
||||
// History
|
||||
function delete_history(histid) {
|
||||
request(`/history/delete/${histid}`, function(xhr) {
|
||||
if (xhr.status != 200) {return;}
|
||||
request(`/history/delete/${histid}`, (response, body) => {
|
||||
if (response.status != 200) {return;}
|
||||
|
||||
const element = document.getElementById(histid);
|
||||
const details = element.parentElement;
|
||||
|
@ -157,20 +148,19 @@ function delete_history(histid) {
|
|||
|
||||
// Search
|
||||
function set_default_search(id) {
|
||||
request(`/search/default/${id}`, function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
request(`/search/default/${id}`, (response, body) => {
|
||||
if (response.status != 200) {
|
||||
console.log(`Failed to set search engine active: ID ${id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (let acct of document.getElementsByClassName('search-item')) {
|
||||
var active = acct.getElementsByClassName('default')[0];
|
||||
|
||||
const active = acct.getElementsByClassName('default')[0];
|
||||
|
||||
if (acct.id == `SEARCH${id}`) {
|
||||
active.style.display = 'none'
|
||||
|
||||
active.style.display = 'none';
|
||||
} else {
|
||||
active.style.display = 'inline-block'
|
||||
active.style.display = 'inline-block';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -179,9 +169,8 @@ function set_default_search(id) {
|
|||
|
||||
// Passwords
|
||||
function copy_password(id) {
|
||||
console.log(id);
|
||||
request(`/passwords/copy/${id}`, function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
request(`/passwords/copy/${id}`, (response, body) => {
|
||||
if (response.status != 200) {
|
||||
console.log(`Error code when trying to copy password: ${xhr.status} ${xhr.statusText}`);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -9,9 +9,14 @@ class LoginRowBase:
|
|||
return self.ui.get_object(key)
|
||||
|
||||
|
||||
@property
|
||||
def app(self):
|
||||
return Gio.Application.get_default()
|
||||
|
||||
|
||||
@property
|
||||
def window(self):
|
||||
return Gio.Application.get_default().window
|
||||
return self.app.window
|
||||
|
||||
|
||||
def connect(self, name, signal, callback, *args, original_args=False, **kwargs):
|
||||
|
@ -25,36 +30,39 @@ class LoginRowBase:
|
|||
class SavedLoginRow(LoginRowBase):
|
||||
def __init__(self, row, page_url):
|
||||
self.ui = Gtk.Builder.new_from_file(dirs.resources.join('password_saved.ui'))
|
||||
self.passrow = row
|
||||
self.tab = self.window.active_tab
|
||||
self.row = row
|
||||
|
||||
with db.session as s:
|
||||
self.dbrow = s.get_passfield(page_url)
|
||||
|
||||
self['username'].set_text(self.passrow['username'])
|
||||
self['username'].set_text(self.row['username'])
|
||||
|
||||
if self.passrow.url != page_url or not self.dbrow:
|
||||
self['fill'].set_sensitive(False)
|
||||
#if self.row.url != page_url or not self.dbrow:
|
||||
#self['fill'].set_sensitive(False)
|
||||
|
||||
self.connect('fill', 'clicked', self.handle_fill_password)
|
||||
self.connect('copy', 'clicked', self.handle_copy_password)
|
||||
self.connect('copy-password', 'clicked', self.handle_copy_password)
|
||||
self.connect('copy-username', 'clicked', self.row.copy_username)
|
||||
|
||||
self['container'].show_all()
|
||||
|
||||
|
||||
def handle_copy_password(self):
|
||||
password = self.passrow.password
|
||||
@property
|
||||
def tab(self):
|
||||
return self.window.active_tab
|
||||
|
||||
self.window.clipboard.set_text(password, -1)
|
||||
self.window.notification('Copied password to clipboard for 30 seconds')
|
||||
TimeoutCallback(30, run_in_gui_thread, self.window.passwords.handle_clear_clipboard, self.window.clipboard, password).start()
|
||||
|
||||
def handle_copy_password(self):
|
||||
self.row.copy_password(60)
|
||||
self.window.notification('Copied password to clipboard for 5 seconds')
|
||||
|
||||
self.window['statusbar-logins-popover'].popdown()
|
||||
|
||||
|
||||
def handle_fill_password(self):
|
||||
self.tab.run_js(f'document.getElementsByName("{self.dbrow.userfield}")[0].value = "{self.passrow.username}"')
|
||||
self.tab.run_js(f'document.getElementsByName("{self.dbrow.passfield}")[0].value = "{self.passrow.password}"')
|
||||
with dirs.resources.join('ext_js/autofill.js').open() as fd:
|
||||
self.tab.run_js(fd.read().replace('USERNAME_VALUE', self.row.username).replace('PASSWORD_VALUE', self.row.password))
|
||||
|
||||
self.window['statusbar-logins-popover'].popdown()
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ from datetime import datetime
|
|||
from secretstorage.collection import Collection, get_collection_by_alias, create_collection
|
||||
from secretstorage.exceptions import ItemNotFoundException, LockedException
|
||||
|
||||
from .functions import TimeoutCallback, get_app, run_in_gui_thread
|
||||
|
||||
|
||||
pass_store_keys = ['username', 'domain', 'url', 'note']
|
||||
pass_keys = [*pass_store_keys, 'created', 'modified', 'label', 'password']
|
||||
|
@ -274,6 +276,18 @@ class PasswordItem:
|
|||
return self.update(note=value)
|
||||
|
||||
|
||||
def copy_password(self, timeout=60):
|
||||
app = get_app()
|
||||
app.set_clipboard_text(self.password)
|
||||
|
||||
timer = TimeoutCallback(timeout, run_in_gui_thread, app.handle_clipboard_clear_password, self.password)
|
||||
timer.start()
|
||||
|
||||
|
||||
def copy_username(self):
|
||||
get_app().set_clipboard_text(self.username)
|
||||
|
||||
|
||||
def as_dict(self):
|
||||
return DotDict(
|
||||
id = self.id,
|
||||
|
|
|
@ -178,7 +178,7 @@ def fediverse_refresh(handler, request, acctid):
|
|||
return request.error(f'Account with ID not found: {acctid}', 404)
|
||||
|
||||
row.refresh()
|
||||
return request.redirect('/fediverse')
|
||||
return request.ok_or_redirect(f'Refreshed account info: {row.fullhandle}')
|
||||
|
||||
|
||||
@Local.route('/fediverse/set_active/{acctid:int}')
|
||||
|
@ -190,8 +190,7 @@ def fediverse_set_active(handler, request, acctid):
|
|||
return request.error(f'Account with ID not found: {acctid}', 404)
|
||||
|
||||
row.set_active()
|
||||
logging.verbose('Set account as active:', row.fullhandle)
|
||||
return request.response('OK')
|
||||
return request.ok_or_redirect(f'Account set as active: {row.fullhandle}')
|
||||
|
||||
|
||||
@Local.route('/fediverse/logout/{acctid:int}')
|
||||
|
@ -349,10 +348,7 @@ def passwords_copy(handler, request, rowid):
|
|||
except KeyError:
|
||||
return request.error(f'Cannot find password: {rowid}', 404)
|
||||
|
||||
handler.app.set_clipboard_text(row.password)
|
||||
|
||||
timer = TimeoutCallback(60, run_in_gui_thread, handler.app.handle_clipboard_clear_password, row.password)
|
||||
timer.start()
|
||||
row.copy_password()
|
||||
|
||||
return request.ok_or_redirect(f'Copied password for 60 seconds')
|
||||
|
||||
|
@ -384,7 +380,7 @@ def preferences_home(handler, request):
|
|||
|
||||
@Local.route('/preferences/update')
|
||||
def preferences_update(handler, request):
|
||||
if not len(request.query):
|
||||
if not len([key for key in request.query.keys() if key != 'redir']):
|
||||
return request.error('No key/value pairs provided', 400)
|
||||
|
||||
with db.session as s:
|
||||
|
@ -395,7 +391,7 @@ def preferences_update(handler, request):
|
|||
row = s.put_config(key, value)
|
||||
logging.verbose(f'Updated config: {row.key} = {row.value}')
|
||||
|
||||
return request.ok_or_redirect('/preferences', 'Updated preferences')
|
||||
return request.ok_or_redirect('Updated preferences')
|
||||
|
||||
|
||||
### Search ###
|
||||
|
|
28
barkshark_web/resources/ext_js/autofill.js
Normal file
28
barkshark_web/resources/ext_js/autofill.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
function fetch_fields() {
|
||||
var userfield = null;
|
||||
var passfield = null;
|
||||
|
||||
Array.from(document.forms).forEach((form) => {
|
||||
Array.from(form.getElementsByTagName('input')).forEach((input) => {
|
||||
if (input.type == 'password') {
|
||||
passfield = input;
|
||||
} else if (input.name.includes('user')) {
|
||||
userfield = input;
|
||||
}
|
||||
|
||||
if (![userfield, passfield].includes(null)) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return [userfield, passfield];
|
||||
}
|
||||
|
||||
|
||||
fields = fetch_fields();
|
||||
|
||||
if (!fields.includes(null)) {
|
||||
fields[0].value = 'USERNAME_VALUE';
|
||||
fields[1].value = 'PASSWORD_VALUE';
|
||||
}
|
|
@ -898,7 +898,7 @@ AND CONDITIONS OF THIS LICENSE.
|
|||
<property name="icon-name">window-close</property>
|
||||
</object>
|
||||
<object class="GtkPopover" id="statusbar-logins-popover">
|
||||
<property name="width-request">400</property>
|
||||
<property name="width-request">500</property>
|
||||
<property name="height-request">400</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
|
|
|
@ -20,8 +20,22 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="copy">
|
||||
<property name="label" translatable="yes">Copy</property>
|
||||
<object class="GtkButton" id="copy-username">
|
||||
<property name="label" translatable="yes">Username</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Copy username to clipboard</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="copy-password">
|
||||
<property name="label" translatable="yes">Password</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
|
|
26
pyvenv.json
26
pyvenv.json
|
@ -49,12 +49,12 @@
|
|||
"izzylib": {
|
||||
"version": "0.1.0",
|
||||
"options": [],
|
||||
"url": "git+https://git.barkshark.xyz/izaliamae/izzylib_sql"
|
||||
"url": "git+https://git.barkshark.xyz/izaliamae/izzylib-sql"
|
||||
},
|
||||
"izzylib_http_async": {
|
||||
"version": "0.1.0",
|
||||
"options": [],
|
||||
"url": "git+https://git.barkshark.xyz/izaliamae/izzylib_http_async"
|
||||
"url": "git+https://git.barkshark.xyz/izaliamae/izzylib-http-async"
|
||||
},
|
||||
"mastodon.py": {
|
||||
"version": "1.5.1",
|
||||
|
@ -81,5 +81,25 @@
|
|||
"options": [],
|
||||
"url": null
|
||||
}
|
||||
},
|
||||
"watcher": {
|
||||
"path": "barkshark_web",
|
||||
"command": "barkshark_web",
|
||||
"env": {"LOG_LEVEL": "VERBOSE"},
|
||||
"ext": [
|
||||
"py",
|
||||
"pyx",
|
||||
"pyc"
|
||||
],
|
||||
"ignore_dirs": [
|
||||
"build",
|
||||
"config",
|
||||
"data"
|
||||
],
|
||||
"ignore_files": [
|
||||
"reload.py",
|
||||
"test.py",
|
||||
"pyvenv.py"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1 @@
|
|||
izzylib[dbus,http_urllib_client,sql,template] @ git+https://git.barkshark.xyz/izaliamae/izzylib@ab87e880a15b3eb2bb1420b6f169653cc00bfcd6
|
||||
|
||||
beautifulsoup4==4.9.3
|
||||
configobj>=5.0.6
|
||||
lxml>=4.6.3
|
||||
mastodon.py==1.5.1
|
||||
pillow==8.3.2
|
||||
psutil==5.8.0
|
||||
pygobject==3.38.0
|
||||
pysftp==0.2.9
|
||||
SecretStorage==3.3.1
|
||||
tldextract==3.1.0
|
||||
validators==0.18.2
|
||||
.
|
||||
|
|
58
setup.cfg
Normal file
58
setup.cfg
Normal file
|
@ -0,0 +1,58 @@
|
|||
[metadata]
|
||||
name = Barkshark Web
|
||||
version = 0.3.8
|
||||
author = Zoey Mae
|
||||
author_email = zoey@barkshark.xyz
|
||||
url = https://git.barkshark.xyz/izaliamae/barkshark-web
|
||||
description = Python venv manager
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown; charset=UTF-8
|
||||
license = CNPL 4+
|
||||
license_file = LICENSE
|
||||
platform = any
|
||||
keywords = python development venv
|
||||
classifiers =
|
||||
Development Status :: 4 - Beta
|
||||
Intended Audience :: End Users/Desktop
|
||||
License :: OSI Approved :: GNU General Public License v3
|
||||
Programming Language :: Python :: 3.8
|
||||
Programming Language :: Python :: 3.9
|
||||
Programming Language :: Python :: 3.10
|
||||
Operating System :: POSIX
|
||||
Operating System :: MacOS :: MacOS X
|
||||
Operating System :: Microsoft :: Windows
|
||||
Topic :: Internet :: WWW/HTTP
|
||||
project_urls =
|
||||
Bug Tracker = https://git.barkshark.xyz/izaliamae/barkshark-web/issues
|
||||
Documentation = https://git.barkshark.xyz/izaliamae/barkshark-web/wiki
|
||||
Source Code = https://git.barkshark.xyz/izaliamae/barkshark-web
|
||||
|
||||
[options]
|
||||
include_package_data = true
|
||||
python_requires = >= 3.8
|
||||
packages =
|
||||
barkshark_web
|
||||
setup_requires =
|
||||
izzylib @ git+https://git.barkshark.xyz/izaliamae/izzylib@a156b3b416a9549ee439adc36785cca4131c499c
|
||||
izzylib_sql @ git+https://git.barkshark.xyz/izaliamae/izzylib-sql@ebfe4fa678f16f35f650afd077a97e4a7cf45d61
|
||||
izzylib_http_async @ git+https://git.barkshark.xyz/izaliamae/izzylib-http-async@216a779f221e926cd3130404bd33cb916f87d21a
|
||||
beautifulsoup4==4.9.3
|
||||
lxml==4.6.3
|
||||
mastodon.py==1.5.1
|
||||
pillow==8.3.2
|
||||
psutil==5.8.0
|
||||
pygobject==3.38.0
|
||||
pysftp==0.2.9
|
||||
SecretStorage==3.3.1
|
||||
tldextract==3.1.0
|
||||
validators==0.18.2
|
||||
|
||||
[options.entry_points]
|
||||
console_scripts =
|
||||
pyvenv = barkshark_web.startup:main
|
||||
|
||||
[bdist_wheel]
|
||||
universal = false
|
||||
|
||||
[sdist]
|
||||
formats = zip, gztar
|
66
setup.py
66
setup.py
|
@ -1,64 +1,2 @@
|
|||
#!/usr/bin/env python3
|
||||
import os, shutil, sys
|
||||
from pathlib import Path
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
scriptpath = Path(__file__).resolve().parent
|
||||
extsetup = scriptpath.joinpath('webextension/build.sh')
|
||||
extloader = scriptpath.joinpath('bsweb/bin/pythonloader.so')
|
||||
extloader_build = scriptpath.joinpath('webextension/pythonloader.so')
|
||||
|
||||
|
||||
with scriptpath.joinpath('requirements.txt').open() as fd:
|
||||
requirements = [req.replace('\n', '') for req in fd.readlines()]
|
||||
|
||||
with scriptpath.joinpath('apt-requirements.txt').open() as fd:
|
||||
apt_requirements = ' '.join([req.replace('\n', '') for req in fd.readlines()])
|
||||
|
||||
#if os.environ.get('APT_INSTALL'):
|
||||
#os.system(f'sudo apt install {apt_requirements} -y --no-install-recommends')
|
||||
|
||||
#extloader.parent.mkdir(exist_ok=True)
|
||||
|
||||
#if not extloader.exists():
|
||||
#os.system(f'cd {scriptpath} && git submodule init')
|
||||
#os.system(extsetup)
|
||||
#shutil.copy(extloader_build, extloader)
|
||||
|
||||
setup(
|
||||
name='pyweb',
|
||||
version='0.3.5',
|
||||
packages=find_packages(),
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'bsweb = bsweb.startup:main'
|
||||
]
|
||||
},
|
||||
python_requires='>=3.8.0',
|
||||
install_requires=requirements,
|
||||
include_package_data=True,
|
||||
|
||||
author='Zoey Mae',
|
||||
author_email='admin@barkshark.xyz',
|
||||
description='Barkshark Web: Simple GTK web browser',
|
||||
keywords='gtk web browser gui',
|
||||
url='https://git.barkshark.xyz/izaliamae/pyweb',
|
||||
project_urls={
|
||||
'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/pyweb/issues',
|
||||
'Documentation': 'https://git.barkshark.xyz/izaliamae/pyweb/wiki/Index',
|
||||
'Source Code': 'https://git.barkshark.xyz/izaliamae/pyweb'
|
||||
},
|
||||
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Intended Audience :: End Users/Desktop',
|
||||
'License :: OSI Approved :: GNU General Public License v3',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Operating System :: POSIX',
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Topic :: Internet :: WWW/HTTP'
|
||||
]
|
||||
)
|
||||
import setuptools
|
||||
setuptools.setup()
|
||||
|
|
Reference in a new issue