You are not logged in.

#3551 2021-05-08 12:39:40

dmz
Member
From: Sweden
Registered: 2008-08-27
Posts: 881
Website

Re: Post your handy self made command line utilities

MangoMan1 wrote:

First post here on the forums.

I love center. I'll be using it. Thanks!

Offline

#3552 2021-05-08 14:19:52

teckk
Member
Registered: 2013-02-21
Posts: 524

Re: Post your handy self made command line utilities

Get the arch news, several different ways, parse it several different ways.
Why? Because it's arch, you need the news, and it's also python practice. Few examples:

#!/usr/bin/python

#Get the Arch Latest News with xml.etree

from xml.etree import ElementTree
from urllib import request
import re

#Make a user agent string for urllib to use
agent = ('Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) '
        'Gecko/20100101 Firefox/86.0')
        
user_agent = {'User-Agent': agent}

class MakeList():
    def __init__(self, url, fname):
    
        #Get the xml to parse
        req = request.Request(url, data=None, headers=user_agent)
        html = request.urlopen(req)
        tree = ElementTree.parse(html)
        root = tree.getroot()
        
        #Get tag data
        tagA = root.findall('./channel/item/title')
        tagB = root.findall('./channel/item/link')
        tagC = root.findall('./channel/item/description')
        tagD = []
        tagR = '<[^>]*>'
        
        #Append lines with separator
        for a,b,c in zip(tagA,tagB,tagC):
            tagD.extend([re.sub(tagR,'',a.text), re.sub(tagR,'',b.text), 
                        re.sub(tagR,'',c.text), '_' * 70])
                        
        
        #Print and Write list to file
        with open(fname, 'a') as f:
            for line in tagD:
                print(line, '\n')
                f.write(line + '\n'*2)
                
if __name__ == "__main__":
    
    #Urls, log names
    A = ('https://archlinux.org/feeds/news/', 'Arch_RSS.log')
    B = ('file:///local/file/archfeed.xml', 'test.log')
    
    #Choose RSS feed here
    url, fname = A

    MakeList(url, fname)
    
______________________________________________________________________

#!/usr/bin/python

#Get the Arch Latest News with xml.dom

from xml.dom import minidom
from urllib import request
import re

#Make a user agent string for urllib to use
agent = ('Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) '
        'Gecko/20100101 Firefox/86.0')
        
user_agent = {'User-Agent': agent}

class MakeList():
    def __init__(self, url, fname):
        
        #Get the xml to parse
        req = request.Request(url, data=None, headers=user_agent)
        xml = request.urlopen(req)
        dat = minidom.parse(xml)
        
        #Get  tag data
        tagA = dat.getElementsByTagName('title')
        tagB = dat.getElementsByTagName('link')
        tagC = dat.getElementsByTagName('description') 
        tagD = [] 
        tagR = '<[^>]*>'
        
        #Append lines with separator
        for i in range(0, len(tagA)):
            A = (tagA[i].firstChild.data)
            B = (tagB[i].firstChild.data)
            C = (tagC[i].firstChild.data)
            tagD.extend([re.sub(tagR,'',A), re.sub(tagR,'',B), 
                        re.sub(tagR,'',C), '_' * 70])
                        
        #Print and Write list to file
        with open(fname, 'a') as f:
            for line in tagD:
                print(line, '\n')
                f.write(line + '\n'*2)
            
if __name__ == "__main__":
    
    #Urls, log names
    A = ('https://archlinux.org/feeds/news/', 'Arch_RSS.log')
    B = ('file:///local/file/archfeed.xml', 'test.log')
    
    #Choose RSS feed here
    url, fname = A

    MakeList(url, fname)
    
______________________________________________________________________
        
#!/usr/bin/python

#Get the Arch Latest News with Beautifulsoup

from bs4 import BeautifulSoup
from urllib import request
import re

agent = ('Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) '
        'Gecko/20100101 Firefox/86.0')
        
user_agent = {'User-Agent': agent}

class MakeList():
    def __init__(self, url, fname):

        #Get the xml to parse
        req = request.Request(url, data=None, headers=user_agent)
        html = request.urlopen(req)
        contents = html.read()
        soup = BeautifulSoup(contents,'xml')
        
        #Get tag data
        titles = soup.find_all('title')
        links = soup.find_all('link')
        del links[1]
        descriptions = soup.find_all('description')
        news=[]
        tagR = '<[^>]*>'
               
        #Append lines with separator
        for a,b,c in zip(titles,links,descriptions):
            news.extend([re.sub(tagR,'',a.text), re.sub(tagR,'',b.text), 
                        re.sub(tagR,'',c.text), '_' * 70])
                        
        #Print and Write list to file
        with open(fname, 'a') as f:
            for line in news:
                print(line, '\n')
                f.write(line + '\n'*2)

if __name__ == "__main__":
    
    #Urls, log names
    A = ('https://archlinux.org/feeds/news/', 'Arch_RSS.log')
    B = ('file:///local/file/archfeed.xml', 'test.log')
    
    #Choose RSS feed here
    url, fname = A

    MakeList(url, fname)
    
______________________________________________________________________
    
#!/usr/bin/python

#Get the Arch Latest News with http.client and re

from http.client import HTTPSConnection
import re

def getSource(url):
    #Get page source
    a = HTTPSConnection(url)
    a.request('GET', '/feeds/news/')
    b = a.getresponse()
    data = b.read().decode('utf-8', errors='ignore')
    a.close()
    
    #Write file, read it
    with open ('arch_rss.xml', 'w+') as f:
        for line in data.split('\n'):
            f.write(line)
        f.seek(0)
        xml = f.read()
        
        #Parse tags with re
        A = re.findall("<title>(.*?)</title>", xml)
        B = re.findall("<link>(.*?)</link>", xml)
        C = re.findall("<description>(.*?)</description>", xml)
        
        #Alternate A,B,C together
        D =[x for y in zip(A, B, C) for x in y]
        
        #Print parsed data
        for line in D:
            print(line, '\n')

url = 'archlinux.org'
getSource(url)

Offline

#3553 2021-05-15 13:45:14

ugjka
Member
From: Latvia
Registered: 2014-04-01
Posts: 1,863
Website

Re: Post your handy self made command line utilities

Lil' something that was a Bash script

package Fetchfriends;
use Carp;
use strict;
use warnings;
use File::Copy;
use MP4::Info;

our $VERSION = '1.0.0';

chdir 'C:\\Users\\ugjka\\FrancisFriendsM4A' or croak 'Files not found!';

system 'pip-review -a --user' and croak 'PIP update failed';

system 'youtube-dl', '-f', '140', '-i',
  '--download-archive', 'list.txt',
  '--add-metadata',
  'https://www.youtube.com/playlist?list=UUHBTezPh7u20jydYYg3j83Q',
  'https://www.youtube.com/playlist?list=UUAYslZlNuBDD7FMvpjWLtoQ',
  'https://www.youtube.com/playlist?list=UU8PdsoinYT_izA5t54l2flg',
  'https://www.youtube.com/playlist?list=UUxXWjjtATq3OM545gMh9PUg'
  and croak 'Video download failed';

my @files = <*.m4a>;
foreach my $file (@files) {
    my $tag = get_mp4tag($file) or croak 'No TAG info';
    if ( !length( $tag->{ART} ) ) {
        croak 'Artist tag empty';
    }

    my $wav     = $file =~ s/[.]m4a/.wav/rmsx;
    my $artist  = $tag->{ART};
    my $title   = $tag->{NAM};
    my $comment = $tag->{CMT};
    my $date    = $tag->{DAY};

    system 'ffmpeg', '-i', $file, '-f', 'wav', $wav
      and croak('Transcode to wav failed');

    unlink $file or croak "deleting ${file} failed";

    system 'fdkaac', '-b', '24000', '-p', '29',
      '--title', $title, '--artist', $artist, '--comment', $comment, '--date',
      $date, $wav
      and system 'fdkaac', '-b', '24000', '-p', '5',
      '--title', $title, '--artist', $artist, '--comment', $comment, '--date',
      $date, $wav
      and croak('Fdkaac encode failed');

    unlink $wav or croak "Deleting ${wav} failed";
    move $file, $artist or croak 'Moving the m4a file failed';

}

print "Uploading to Google Drive\n";
system
'rclone --log-level INFO copy C:\\Users\\ugjka\\FrancisFriendsM4A francis:FrancisFriendsM4A';

1;

https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...

Offline

#3554 2021-05-17 14:58:10

Alad
Wiki Admin/IRC Op
From: Bagelstan
Registered: 2014-05-04
Posts: 2,418
Website

Re: Post your handy self made command line utilities

Lil' something that was a Bash script

Why do you hardcode the URLs in your script? Perl has ARGV like anything else. You could also store those URLs in a seperate file that is read from the script.

Last edited by Alad (2021-05-17 15:03:38)


Mods are just community members who have the occasionally necessary option to move threads around and edit posts. -- Trilby

Offline

#3555 2021-05-17 15:02:21

lenhuppe
Member
From: New Hampshire USA
Registered: 2018-12-10
Posts: 281
Website

Re: Post your handy self made command line utilities

Alad wrote:

Why do you hardcode the URLs in your script? Perl has ARGV like anything else. You could also store those URLs in a seperate file that is read from the script.

Which post are you referring to?


"I'm suspicious of people who don't like dogs, but I trust a dog when it doesn't like a person."  -- Bill Murray

Offline

#3556 2021-05-17 15:03:19

Alad
Wiki Admin/IRC Op
From: Bagelstan
Registered: 2014-05-04
Posts: 2,418
Website

Re: Post your handy self made command line utilities

The one above it... #3553. I'll edit in a quote.


Mods are just community members who have the occasionally necessary option to move threads around and edit posts. -- Trilby

Offline

#3557 2021-05-17 16:41:29

ugjka
Member
From: Latvia
Registered: 2014-04-01
Posts: 1,863
Website

Re: Post your handy self made command line utilities

Alad wrote:

Lil' something that was a Bash script

Why do you hardcode the URLs in your script? Perl has ARGV like anything else. You could also store those URLs in a seperate file that is read from the script.

I know about ARGV and stuff, those URLs will never change and there probably won't be removals or additions. I don't see the point for extra logic but thanks for heads up smile

EDIT: those URLs aren't sensitive, just public channels of Advaita Vedanta teachers

Last edited by ugjka (2021-05-17 16:50:27)


https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...

Offline

#3558 2021-05-17 22:31:19

icar
Member
From: Catalunya
Registered: 2020-07-31
Posts: 506

Re: Post your handy self made command line utilities

I adapted the fzf one liner for pacman in https://wiki.archlinux.org/title/Fzf#Ar … c_fzf_uses for Flatpak, using fzf Rust counterpart skim. I know it's not a welcomed technology here, but I guess I'd share it:

flatpak remote-ls flathub --system --cached --app --columns=application:f,description:f | sk --multi --preview 'flatpak remote-info flathub {1}' --preview-window=right:30% | awk '{print \$1}' | xargs -ro flatpak install --system --or-update flathub

flatpak list --system --app --columns=application:f,description:s | sk --multi --preview 'flatpak info {1}' | xargs -ro flatpak uninstall

Offline

#3559 2021-06-02 17:29:34

lmn
Member
Registered: 2021-05-09
Posts: 68

Re: Post your handy self made command line utilities

I keep offline documentation for stuff I use regularly and use this script for selecting and opening.

#!/bin/sh

dir="${1:-.}"
[ ! -d "$dir" ] && exit 1 

cd "$dir"

find . -type f \
	| sed 's|^./||' \
	| sort -n \
	| fzf -e --reverse --height 40% --info=inline --border \
	| xargs -r xdg-open 

fzf can be replaced by some other selector.
sort and sed are just for cosmetics.

Offline

#3560 2021-06-02 19:15:29

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

@lmn, nice.
I use a similar one liner no fzf but dmenu used to open whatever...

Two things, 'cd' that's ugly! there's no need at all...   'find "$dir"' unless you're really disturbed by the full path of course :lol

xargs, not all script / document / whatever names are well formed, specially downloaded ones: 'xargs -0'

Offline

#3561 2021-06-02 20:09:03

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: Post your handy self made command line utilities

qinohe wrote:

'find "$dir"' unless you're really disturbed by the full path of course

And even if you are disturbed by that, if you are using gnu-find

find "$dir" -type f -printf %P\\n

Side note, this gets rid of the need for the sed command.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#3562 2021-06-02 21:00:58

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

Trilby wrote:

And even if you are disturbed by that, if you are using gnu-find

find "$dir" -type f -printf %P\\n

Side note, this gets rid of the need for the sed command.

I know, and it looks nice indeed  I use it to enumerate items in some cases.

In this situation it won't work if your search is 'Documents' and you open 'Documents/pdf/awk_course.pdf'

You'll get a message the pdf doesn't exist, at least that counts when using dmenu, haven't tried fzf but I think it's the same result.

edit: used this command:

find "$dir" -type f -printf "%P\n"  | sort -n | fzf -e --reverse --height 40% --info=inline --border | xargs -r -0 xdg-open

I even installed 'fzf' to try if it's fuzzy find work in magical ways, it doesn't..  back to dmenu it is;)
BTW. it wouldn't even work if you set '-maxdepth 1'

Last edited by qinohe (2021-06-02 21:38:23)

Offline

#3563 2021-06-13 18:48:21

tzihad
Member
From: Bangladesh
Registered: 2020-08-14
Posts: 4

Re: Post your handy self made command line utilities

Made a script to change yakuake/konsole theme with GNOME - Night theme Switcher  Extension

.zshrc

source /home/zihad/.required/shell_startup.sh
autoload -U add-zsh-hook
add-zsh-hook precmd konsoleswitchtheme


shell_startup.sh

#!/bin/zsh
konsoledark () {
  konsoleprofile colors=Sweet
}
konsolelight () {
  konsoleprofile colors=Light
}
konsoleswitchtheme () {
ENV_THEME=$(cat /home/zihad/.required/pipe/ENV_THEME)
  if [[ "$ENV_THEME" = *"Light"* ]]; then
      konsolelight  
  else 
      konsoledark
  fi
  # /home/zihad/.required/themequery
  # ret=$?
  # if [ $ret -ne 0 ]; then
  #     konsolelight  
  # else 
  #     konsoledark
  # fi
}
konsoleswitchtheme

dark.sh

#!/bin/bash
#/home/zihad/.required/themechanged 0
echo Dark > /home/zihad/.required/pipe/ENV_THEME

light.sh

#!/bin/bash
#/home/zihad/.required/themechanged 1
echo Light > /home/zihad/.required/pipe/ENV_THEME

Offline

#3564 2021-06-13 20:18:39

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

@tzihad, Not that I don't like your script but isn't it a little over the top :-)
This would do the same, put under a quick button and forget the other scripts...

konsoleswitchtheme () {
env_theme='/home/zihad/.required/pipe/ENV_THEME'
  if [[ $(<"$env_theme") != light ]]; then
      sed -i 's/dark/light/'  "$env_theme"
  else 
      sed -i 's/light/dark/'  "$env_theme"
  fi
}
konsoleswitchtheme

Offline

#3565 2021-06-14 18:46:48

tzihad
Member
From: Bangladesh
Registered: 2020-08-14
Posts: 4

Re: Post your handy self made command line utilities

@qinohe  I am not good with bash. But , as far as I guess your script is for toggling the Light/Dark in the $env_theme file. What is wanted to do is to toggle the konsole theme with the Night theme switcher plugin. You are right that adding

konsoleswitchtheme

in the zsh-hooks isn't a good idea, a hotkey would be an efficient solution.

Offline

#3566 2021-06-14 19:14:12

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: Post your handy self made command line utilities

I'm not sure what is needed, but if toggling the content of a file from "light" to "dark" is all, then there's definitely no need for reading the file, a [[ test, an if/else block, and two calls to sed.  Just use sed to toggle the content:

sed -i 's/light/dark/;tq;s/dark/light/;:q' "$env_theme"

"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#3567 2021-06-14 19:23:57

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

Trilby wrote:

I'm not sure what is needed, but if toggling the content...]

Haha, now that's nice sed usage!
If I knew about it I posted it, thanks - learning every day;-)

edit:@tzihad, completely missed you reacted too, yes it's for the toggle.
My function became moot after Trilby posted that one-liner...

Last edited by qinohe (2021-06-14 21:19:01)

Offline

#3568 2021-06-15 08:33:33

tzihad
Member
From: Bangladesh
Registered: 2020-08-14
Posts: 4

Re: Post your handy self made command line utilities

@qinohe Actually in my case, I use Night theme switcher for changing the theme with an button on status bar. This extension calls the light.sh and dark.sh accordingly.So, this extension does the toggle.The script i provided changes the content of ENV_THEME and the hook `konsoleswiththeme` runs command according to the contents of ENV_THEME file

Last edited by tzihad (2021-06-15 11:27:27)

Offline

#3569 2021-06-15 15:01:43

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

I understand, just reacted on the switch script. About the rest of that small scripts you use, they are fine if it gets the job done for you. I just don't have an opinion about it for I have one GTK theme for i3 and I never switch. There is one switcher I use for dmenu that used to use that function I pasted and since yesterday replaced it with that one-liner Trilby posted...

Offline

#3570 2021-07-01 08:45:32

kokoko3k
Member
Registered: 2008-11-14
Posts: 2,421

Re: Post your handy self made command line utilities

This is xfreeze.sh, works on Xorg and may require kdialog, but can be used with equivalent tools.

LIke xkill, when started it expects you to click on a window, then it asks you if you want to pause it or resume the "process you clicked".
Handy when you are playing something and don't want to steal cpu cycles while you're taking a break from the break.
if called with the "active" parameter, it does not expect a click, but asks what to do with the actual active window.
I've bound "xfreeze.sh active" it to the shortcut: shift+pause, handy.

#!/usr/bin/env bash
if [ $1 = "active" ] ; then
	PROC=$(xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}')
		else
	PROC=$(xdotool selectwindow getwindowpid)
fi
if kdialog --yesno $(</proc/$PROC/comm) --yes-label RESUME --no-label PAUSE ; then
	kill -CONT $PROC
		else
	kill -STOP $PROC
fi

Getting the process of the active window seems tricky (I copy pasted with no shame from 'the internet'), if somebody has a better way...
Also, maybe it would be better to just "switch" the state of the process instead of asking everytime what to do.

-EDIT-
More advanced version:

#!/usr/bin/env bash

# xfreeze.sh [ask|switch] [active|select]

# ask = ask to pause or continue execution
# switch = switch execution state

# active = use the active window
# select = ask user to click on a window


if [ $2 = "active" ] ; then
	PROC=$(xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}')
		else
	PROC=$(xdotool selectwindow getwindowpid)
fi

if [ $1 = "ask" ] ; then
	kdialog --yesno $(</proc/$PROC/comm) --yes-label RESUME --no-label PAUSE
		else
	grep State: /proc/$PROC/status|grep stopped
fi
condition_continue=$?
echo $condition_continue 

if [ $condition_continue = 0 ] ; then 
	echo cont
	kill -CONT $PROC
		else
	echo stop
	kill -STOP $PROC
fi

cat /proc/$PROC/status

"xfreeze.sh switch active" is fun :-)

Last edited by kokoko3k (2021-07-01 09:57:58)


Help me to improve ssh-rdp !
Retroarch User? Try my koko-aio shader !

Offline

#3571 2021-08-02 16:54:41

Docbroke
Member
From: India
Registered: 2015-06-13
Posts: 1,438

Re: Post your handy self made command line utilities

This is menu, not unlike dmenu_run, but with few changes.
1. When it is run from window manager/shortcut it uses rofi, and when run from terminal it uses fzf/fzy. Therefor it is usable from virutal terminal/wm or console.
2. It allows adding some special commands on top of the list ( in addition to all that is in $PATH ), so I can run things like "weaver  www.google.com" , "terminator -x nnn -Rfe" or "vncviewer -Fullscreen -LowColorLevel 0 piserver"

#!/bin/bash

shopt -s lastpipe
removedups () 
{ 
    f=$(mktemp);
    awk '!x[$0]++' "$1" > "$f";
    mv "$f" "$1"
}

path ()
{
find $(echo $PATH | tr ':' ' ') -type f -executable | sed 's/^.*\///g'
}


## make a temporary file to list all commands
p=$(mktemp)
## add some personal commands first (on the top)
cat $HOME/.config/shortcuts > "$p"
## add all commands from path
path >> "$p"
## remove duplicates
removedups "$p" 
## choose command to execute using fzy (if run from terminal) or rofi (if run using window-manager shortcut)
if [[ $TERM = linux && -n $DISPLAY ]]; then
	 rofi -dmenu -font "Noto Sans Mono Medium 18" -input $p | read command
else
#	fzy < $p | read command 
	fzf --no-sort --reverse --height 10 < $p | read command 
fi
## run the command
exec $command &

Last edited by Docbroke (2021-08-02 18:11:40)

Offline

#3572 2021-08-02 18:24:27

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: Post your handy self made command line utilities

FYI, your "path" function could just be this:

IFS=:; find $PATH -type f -executable -printf "%f\n"

"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#3573 2021-08-02 19:24:28

Docbroke
Member
From: India
Registered: 2015-06-13
Posts: 1,438

Re: Post your handy self made command line utilities

That is indeed good suggestion, but something unusual happens when I use that command.
However after good half an hour, I was able to find out what was wrong. That path function messed up with rest of the script due to "IFS=:", so I had to add IFS=" " after find command. Otherwise all commands with spaces(which I had added like examples in previous post) failed to execute.

Offline

#3574 2021-08-02 19:36:46

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: Post your handy self made command line utilities

Ah, that's true, but you should either store and restore the original value, or much simpler, just run the find in a subshell with IFS set:

(IFS=:; find ...) >> "$p"

Last edited by Trilby (2021-08-02 19:37:10)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#3575 2021-08-02 20:11:41

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,494

Re: Post your handy self made command line utilities

Trilby wrote:

Ah, that's true, but you should either store and restore the original value, or much simpler, just run the find in a subshell with IFS set:

(IFS=:; find ...) >> "$p"

And remove that remove function... and sort it?

(IFS=:; find $PATH -type f -executable -printf "%f\n" | awk '!NF || !x[$0]++' | sort -r ) >> "$p"

edit: also, you're using mktemp so I would cleanup after running:

app_this="${0##*/}"

cleanup_p() {
    if [[ -f "${p}" ]]; then
        rm -rf -- "${p}"
    fi
}
...
p=$(mktemp /tmp/"${app_this}".XXXXX)
...
trap cleanup_p EXIT

Last edited by qinohe (2021-08-02 22:04:19)

Offline

Board footer

Powered by FluxBB