Merge remote-tracking branch 'ni/master'

This commit is contained in:
lassulus 2020-05-25 16:08:23 +02:00
commit bf77db8365
14 changed files with 444 additions and 23 deletions

View File

@ -29,21 +29,37 @@
"140.82.126.*"
"140.82.127.*"
"13.114.40.48"
"13.229.188.59"
"52.192.72.89"
"52.69.186.44"
"15.164.81.167"
"52.78.231.108"
"13.234.176.102"
"13.234.210.38"
"13.229.188.59"
"13.250.177.223"
"52.74.223.119"
"13.236.229.21"
"13.237.44.5"
"13.250.177.223"
"15.164.81.167"
"18.194.104.89"
"18.195.85.27"
"35.159.8.160"
"52.192.72.89"
"52.64.108.95"
"52.69.186.44"
"52.74.223.119"
"52.78.231.108"
"18.228.52.138"
"18.228.67.229"
"18.231.5.6"
"18.181.13.223"
"54.238.117.237"
"54.168.17.15"
"3.34.26.58"
"13.125.114.27"
"3.7.2.84"
"3.6.106.81"
"18.140.96.234"
"18.141.90.153"
"18.138.202.180"
"52.63.152.235"
"3.105.147.174"
"3.106.158.203"
"54.233.131.104"
"18.231.104.233"
"18.228.167.86"
];
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==";
};

View File

@ -16,10 +16,4 @@ foldl' mergeAttrs {}
reaktor2 = self.haskellPackages.reaktor2;
ReaktorPlugins = self.callPackage ./simple/Reaktor/plugins.nix {};
# https://github.com/proot-me/PRoot/issues/106
proot = self.writeDashBin "proot" ''
export PROOT_NO_SECCOMP=1
exec ${super.proot}/bin/proot "$@"
'';
}

View File

@ -4,11 +4,11 @@
}:
mkDerivation {
pname = "flameshot-once";
version = "1.2.0";
version = "1.3.0";
src = fetchgit {
url = "https://cgit.krebsco.de/flameshot-once";
sha256 = "01c11dk8ss37awfn9xqsgx668dcrf4kvzfxlq7ycnqsnpbjjvm0a";
rev = "cebaefa37095e74ad2253c4e2f9d9ab390f88737";
sha256 = "1jy73379srnkq79i7k3al406r0kb3pxwgg6f64i89jhzxjn7zmzl";
rev = "81ce6b9bb68c2739ec5bda067fcfaeab931d55dd";
fetchSubmodules = true;
};
isLibrary = false;

View File

@ -0,0 +1,51 @@
with import <stockholm/lib>;
self: super: {
flameshot = super.flameshot.overrideAttrs (old: rec {
patches = old.patches or [] ++ [
(self.writeText "flameshot-imgur.patch" /* diff */ ''
--- a/src/tools/imgur/imguruploader.cpp
+++ b/src/tools/imgur/imguruploader.cpp
@@ -40,6 +40,7 @@
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
+#include <stdlib.h>
ImgurUploader::ImgurUploader(const QPixmap &capture, QWidget *parent) :
QWidget(parent), m_pixmap(capture)
@@ -74,7 +75,10 @@ void ImgurUploader::handleReply(QNetworkReply *reply) {
QJsonObject json = response.object();
QJsonObject data = json["data"].toObject();
m_imageURL.setUrl(data["link"].toString());
- m_deleteImageURL.setUrl(QString("https://imgur.com/delete/%1").arg(
+ char *deleteImageURLPattern = secure_getenv("IMGUR_DELETE_URL");
+ if (deleteImageURLPattern == NULL)
+ deleteImageURLPattern = "https://imgur.com/delete/%1";
+ m_deleteImageURL.setUrl(QString(deleteImageURLPattern).arg(
data["deletehash"].toString()));
onUploadOk();
} else {
@@ -105,7 +109,10 @@ void ImgurUploader::upload() {
QString description = FileNameHandler().parsedPattern();
urlQuery.addQueryItem("description", description);
- QUrl url("https://api.imgur.com/3/image");
+ char *createImageURLPattern = secure_getenv("IMGUR_CREATE_URL");
+ if (createImageURLPattern == NULL)
+ createImageURLPattern = "https://api.imgur.com/3/image";
+ QUrl url(createImageURLPattern);
url.setQuery(urlQuery);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,
'')
];
});
# https://github.com/proot-me/PRoot/issues/106
proot = self.writeDashBin "proot" ''
export PROOT_NO_SECCOMP=1
exec ${super.proot}/bin/proot "$@"
'';
}

View File

@ -16,6 +16,7 @@ in
pkgs.flameshot
pkgs.qt5.qtbase
pkgs.xclip
pkgs.xwaitforwindow
]}
${optionalString (config != null) /* sh */ ''
. ${import ./profile.nix { inherit config pkgs; }}

View File

@ -48,7 +48,9 @@ let
"SAVE"
"EXIT"
"BLUR"
];
]
++ optional cfg.imgur.enable "IMAGEUPLOADER"
;
type = types.listOf (types.enum (attrNames ButtonType));
};
disabledTrayIcon = mkOption {
@ -65,6 +67,44 @@ let
# This is types.filename extended by [%:][%:+]*
types.addCheck types.str (test "[%:0-9A-Za-z._][%:+0-9A-Za-z._-]*");
};
imgur = mkOption {
default = {};
type = types.submodule {
options = {
enable = mkEnableOption "imgur";
createUrl = mkOption {
example = "http://p.r/image";
type = types.str;
};
deleteUrl = mkOption {
example = "http://p.r/image/delete/%1";
type = types.str;
};
xdg-open = mkOption {
default = {};
type = types.submodule {
options = {
enable = mkEnableOption "imgur.xdg-open" // {
default = true;
};
browser = mkOption {
default = "${pkgs.coreutils}/bin/false";
type = types.str;
};
createPrefix = mkOption {
default = cfg.imgur.createUrl;
type = types.str;
};
deletePrefix = mkOption {
default = removeSuffix "/%1" cfg.imgur.deleteUrl;
type = types.str;
};
};
};
};
};
};
};
savePath = mkOption {
default = "/tmp";
type = types.absolute-pathname;
@ -135,4 +175,30 @@ in
export FLAMESHOT_CAPTURE_PATH=${cfg.savePath}
export FLAMESHOT_ONCE_TIMEOUT=${toString cfg.timeout}
export XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
${optionalString cfg.imgur.enable /* sh */ ''
export IMGUR_CREATE_URL=${shell.escape cfg.imgur.createUrl}
export IMGUR_DELETE_URL=${shell.escape cfg.imgur.deleteUrl}
${optionalString cfg.imgur.xdg-open.enable /* sh */ ''
PATH=$PATH:${makeBinPath [
(pkgs.writeDashBin "xdg-open" ''
set -efu
uri=$1
prefix=$(${pkgs.coreutils}/bin/dirname "$uri")
case $prefix in
(${shell.escape cfg.imgur.xdg-open.createPrefix})
echo "opening image in browser: $uri" >&2
exec ${config.imgur.xdg-open.browser} "$uri"
;;
(${shell.escape cfg.imgur.xdg-open.deletePrefix})
echo "deleting image: $uri" >&2
exec ${pkgs.curl}/bin/curl -fsS -X DELETE "$uri"
;;
(*)
echo "don't know how to open URI: $uri" >&2
exit 1
esac
'')
]}
''}
''}
''

View File

@ -0,0 +1,29 @@
with import <stockholm/lib>;
{ attr, coreutils, exiv2, findutils, gnugrep, jq, nix, utillinux, stdenv }:
stdenv.mkDerivation rec {
pname = "htgen-imgur";
version = "1.0.0";
src = ./src;
buildPhase = ''
(
exec > htgen-imgur
echo PATH=${makeBinPath [
attr
coreutils
exiv2
findutils
gnugrep
jq
nix utillinux
]}
echo STATEDIR=${shell.escape "\${STATEDIR-$HOME}"}
cat $src/htgen-imgur
)
'';
installPhase = ''
install -D htgen-imgur $out/bin/htgen-imgur
'';
}

View File

@ -0,0 +1,209 @@
find_item() {
if test ${#1} -ge 7; then
set -- "$(find "$STATEDIR/items" -mindepth 1 -maxdepth 1 \
-regex "$STATEDIR/items/$1[0-9A-Za-z]*$")"
if test -n "$1" && test $(echo "$1" | wc -l) = 1; then
echo "$1"
return 0
fi
fi
return 1
}
# https://api.imgur.com/models/basic
basic_response() {(
status_code=$1
status_reason=$2
data=${3-null}
response_body=$(jq -cn \
--argjson data "$data" \
--argjson status "$status_code" \
'
{
data: $data,
status: $status,
success: (200 <= $status and $status <= 299),
}
')
printf "HTTP/1.1 $status_code $status_reason\r\n"
printf 'Connection: close\r\n'
printf 'Content-Length: %d\r\n' $(expr ${#response_body} + 1)
printf 'Content-Type: application/json; charset=UTF-8\r\n'
printf 'Server: %s\r\n' "$Server"
printf '\r\n'
printf '%s\n' "$response_body"
)}
file_response() {
jq -n -r \
--argjson data "$(attr -q -g data "$1")" \
--arg server "$Server" \
'
[ "HTTP/1.1 200 OK\r"
, "Connection: close\r"
, "Content-Length: \($data.size)\r"
, "Content-Type: \($data.type)\r"
, "Server: \($server)\r"
, "\r"
][]
'
cat "$1"
}
read_uri() {
jq -cn --arg uri "$1" '
$uri |
capture("^((?<scheme>[^:]*):)?(//(?<authority>[^/]*))?(?<path>[^?#]*)([?](?<query>[^#]*))?([#](?<fragment>.*))?$") |
. + {
query: (.query | if . != null then
split("&") |
map(split("=") | {key:.[0],value:.[1]}) |
from_entries
else . end)
}
'
}
uri=$(read_uri "$Request_URI")
path=$(jq -nr --argjson uri "$uri" '$uri.path')
case "$Method $path" in
'POST /image')
echo create image >&2
content=$(mktemp -t htgen.$$.content.XXXXXXXX)
trap "rm $content >&2" EXIT
case ${req_expect-} in 100-continue)
printf 'HTTP/1.1 100 Continue\r\n\r\n'
esac
head -c $req_content_length > $content
sha256=$(sha256sum -b $content | cut -d\ -f1)
base32=$(nix-hash --to-base32 --type sha256 $sha256)
item=$STATEDIR/items/$base32
if ! test -e $item; then
mkdir -v -p $STATEDIR/items >&2
cp -v $content $item >&2
fi
base32short=$(echo $base32 | cut -b-7)
scheme=${req_x_forwarded_proto-http}
link=$scheme://$req_host/image/$base32short
if item=$(find_item $base32short); then
deletehash=$(uuidgen)
info=$(
exiv2 print "$item" |
jq -csR '
split("\n") |
map(
match("^(.*\\S)\\s*:\\s*(.*)").captures |
map(.string) |
{key:.[0],value:.[1]}
) |
from_entries |
. + (
.["Image size"] |
match("^(?<width>[0-9]+)\\s*x\\s*(?<height>[0-9]+)$").captures |
map({key:.name,value:(.string|tonumber)}) |
from_entries
) |
. + (
.["File size"] |
match("^(?<size>[0-9]+)\\s*Bytes$").captures |
map({key:.name,value:(.string|tonumber)}) |
from_entries
) |
.
'
)
data=$(jq -cn \
--arg deletehash "$deletehash" \
--arg id "$base32" \
--arg link "$link" \
--argjson info "$info" \
--argjson uri "$uri" \
'
{
id: $id,
title: $uri.query.title,
description: $uri.query.description,
datetime: now,
type: $info["MIME type"],
animated: false,
width: $info.width,
height: $info.height,
size: $info.size,
views: 0,
bandwidth: 0,
vote: null,
favorite: false,
nsfw: null,
section: null,
account_url: null,
acount_id: 0,
is_ad: false,
is_most_viral: false,
tags: [],
ad_type: 0,
ad_url: "",
in_gallery: false,
deletehash: @uri "\($id)?deletehash=\($deletehash)",
name: "",
link: $link,
}
')
attr -q -s deletehash -V "$deletehash" "$item"
attr -q -s data -V "$data" "$item"
basic_response 200 OK "$data"
exit
fi
;;
'GET /image/'*)
basename=$(basename "$path")
if printf %s "$basename" | grep -q '^[0-9a-z]\+$'; then
if item=$(find_item "$basename"); then
echo get image >&2
file_response "$item"
exit
fi
fi
;;
'DELETE /image/delete/'*)
basename=$(basename "$path")
if printf %s "$basename" | grep -q '^[0-9a-z]\+$'; then
if item=$(find_item "$basename"); then
deletehash=$(jq -nr --argjson uri "$uri" '$uri.query.deletehash')
stored_deletehash=$(attr -q -g deletehash "$item")
if test "$deletehash" = "$stored_deletehash"; then
echo "delete image" >&2
rm -v "$item" >&2
basic_response 200 OK
exit
else
echo "delete image error: bad deletehash provided: $deletehash" >&2
basic_response 401 'Unauthorized'
exit
fi
fi
fi
;;
esac

View File

@ -1,14 +1,14 @@
{ coreutils, dash, fetchgit, gnused, stdenv, ucspi-tcp }:
with import <stockholm/lib>;
let
version = "1.2.2";
version = "1.2.3";
in stdenv.mkDerivation {
name = "htgen-${version}";
src = fetchgit {
url = "http://cgit.krebsco.de/htgen";
rev = "refs/tags/v${version}";
sha256 = "0a8vn35vq6pxgk6d3d2cjp0vdxzq9nqf0zgkvnd6668v4cmdf91b";
sha256 = "0lml336w31ckgspp633ym2jnppzln3f8mvmy3y2vz9yanf59j0hb";
};
installPhase = ''

View File

@ -0,0 +1,15 @@
{ writeDashBin, xdotool, xorg }:
writeDashBin "xwaitforwindow" ''
# usage: xwaitforwindow ARGS
# see xdotool search for possible ARGS
# example: xwaitforwindow -name WINDOWNAME
set -efu
if id=$(${xdotool}/bin/xdotool search "$@"); then
printf 'waiting for window %#x\n' "$id" >&2
exec ${xorg.xprop}/bin/xprop -spy -id "$id" >/dev/null
else
printf 'no window found with xdotool search %s\n' "$*" >&2
exit 1
fi
''

25
tv/2configs/imgur.nix Normal file
View File

@ -0,0 +1,25 @@
with import <stockholm/lib>;
{ config, pkgs, ... }: {
services.nginx.virtualHosts."ni.r" = {
locations."/image" = {
extraConfig = /* nginx */ ''
client_max_body_size 20M;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:${toString config.krebs.htgen.imgur.port};
proxy_pass_header Server;
'';
};
};
krebs.htgen.imgur = {
port = 7771;
script = /* sh */ ''
(. ${pkgs.htgen-imgur}/bin/htgen-imgur)
'';
};
}

View File

@ -108,6 +108,13 @@ in {
};
path = [
config.tv.slock.package
(pkgs.flameshot-once.override {
config.imgur.enable = true;
config.imgur.createUrl = "http://ni.r/image";
config.imgur.deleteUrl = "http://ni.r/image/delete/%1";
config.imgur.xdg-open.browser = "/etc/profiles/per-user/tv/bin/cr";
config.timeout = 200;
})
pkgs.fzmenu
pkgs.pulseaudioLight.out
pkgs.rxvt_unicode

View File

@ -3,6 +3,9 @@ module Paths where
import Helpers.Path
flameshot :: FilePath
flameshot = findExecutable "flameshot-once"
otpmenu :: FilePath
otpmenu = findExecutable "otpmenu"

View File

@ -22,7 +22,8 @@ import qualified XMonad.StackSet as W
import Data.Map (Map)
import qualified Data.Map as Map
import XMonad.Hooks.UrgencyHook (SpawnUrgencyHook(..), withUrgencyHook)
import XMonad.Hooks.ManageHelpers (doCenterFloat)
import XMonad.Hooks.ManageHelpers (doCenterFloat,doRectFloat)
import Data.Ratio
import XMonad.Hooks.Place (placeHook, smart)
import XMonad.Actions.PerWorkspaceKeys (chooseAction)
@ -66,6 +67,8 @@ mainNoArgs = do
composeAll
[ appName =? "fzmenu-urxvt" --> doCenterFloat
, appName =? "pinentry" --> doCenterFloat
, title =? "Upload to Imgur" -->
doRectFloat (W.RationalRect 0 0 (1 % 8) (1 % 8))
, placeHook (smart (1,0))
]
, startupHook =
@ -163,6 +166,8 @@ myKeys conf = Map.fromList $
, ((_4, xF86XK_AudioMute), pavucontrol [])
, ((_4, xK_Prior), forkFile Paths.xcalib ["-invert", "-alter"] Nothing)
, ((0, xK_Print), forkFile Paths.flameshot [] Nothing)
]
where
_4 = mod4Mask