Add implementation of ducksel.xyz/prop/usernames

This commit is contained in:
D-u-c-k-s-e-l 2025-07-23 00:10:46 -05:00
parent 6bb66e3b88
commit 6548d97be8
4 changed files with 237 additions and 8 deletions

99
website/_data/anyat.yml Normal file
View file

@ -0,0 +1,99 @@
# Anyat Configuration File
# This file defines the configuration for the Anyat plugin, including linkers and settings.
# If false, Anyat will do nothing.
enabled: true
settings:
# Weather to process pages
process_pages: true
# Weather to process posts
process_posts: true
# Weather to process collections
# If false, Anyat will not process collections.
# If true, Anyat will process collections.
# If you wish to select only some collections,
# set this to a list of the names of the collections
# you want to process.
process_collections: true
# Linkers configuration
# Each linker defines how to format and link a specific platform or service.
# The badge will display an icon showing what the link is for.
# - ### Values
# - format and domain values will replace ^u with the username, and ^d with the domain.
# - format is what is displayed to the user
# - link is the URL that the user will be directed to when clicking the link
# - badge is a textual icon that indicates what platform is being linked to
# - domain is the default domain, explained in # Domains
# - ### Domains
# - If a domain is supplied by the user, the format_domain will be attempted
# and if it doesn't exist, the regular format will be used.
# - The same applies to link and link_domain.
# - If no domain is supplied, the format and link will apply the default
# domain, which is defined in the linkers.
# - When no domain is supplied by the user, the format and link are used
# by default and if not found, the format_domain and link_domain
# will be used instead.
# - When writing linkers, it is recommended to use the NerdFont 'md' icons
# for the badge.
# - If instead of parameters, you provide the name of another linker,
# the string linker will become an alias to the other linker.
linkers:
github:
badge: "\U000f02a4" # nf-md-github
format: "^u"
link: "https://github.com/^u"
w: wafrn
wafrn:
badge: "w"
format: "@^u"
format_domain: "@^u@^d"
link: "https://w.linuxposting.xyz/blog/^u"
link_domain: "https://w.linuxposting.xyz/blog/@^u@^d"
fedi: mainwafrn # alias fedi to use wafrn
mainwafrn: # For less clunky main wafrn links
badge: "w"
format: "@^u"
format_domain: "@^u@^d"
link: "https://app.wafrn.net/blog/^u"
link_domain: "https://app.wafrn.net/blog/@^u@^d"
matrix:
badge: "[M]"
domain: "linuxposting.xyz" # default domain is local
format: "@^u"
format_domain: "@^u:^d"
link_domain: "https://matrix.to/#/@^u:^d"
mail: email
email:
badge: "\U000f01ee" # nf-md-email
domain: "linuxposting.xyz"
format: "^u@^d"
link: "mailto:^u@^d"
t: tumblr
tumblr:
badge: "\uf173" # nf-fa-tumblr
format: "@^u"
link: "https://tumblr.com/^u"
x: twitter # alias x to use twitter
twitter:
badge: "\U000f0544" # nf-md-twitter
format: "@^u"
link: "https://twitter.com/^u"
twitch:
badge: "\U000f0543" # nf-md-twitch
format: "@^u"
link: "https://twitch.tv/^u"
yt: youtube
youtube:
badge: "\U000f05c3" # nf-md-youtube
format: "^u"
link: "https://youtube.com/@^u"
reddit:
badge: "\U000f044d" # nf-md-reddit
format: "u/^u"
link: "https://reddit.com/u/^u"
subreddit:
badge: "\U000f044d" # nf-md-reddit
format: "r/^u"
link: "https://reddit.com/r/^u"

117
website/_plugins/anyat.rb Normal file
View file

@ -0,0 +1,117 @@
module Jekyll
class AnyAt < Jekyll::Generator
safe true
priority :low
def generate(site)
# Load configuration from data file
config = site.data['anyat'] || {}
return unless config['enabled']
# Process all pages and posts
combined_applicable = []
if config['settings']['process_pages']
combined_applicable += site.pages
end
if config['settings']['process_posts']
combined_applicable += site.posts.docs
end
if config['settings']['process_collections'] == true
combined_applicable += site.collections.values.map(&:docs).flatten
elif config['settings']['process_collections'].is_a?(Array)
for collection_name in config['settings']['process_collections']
if site.collections.key?(collection_name)
combined_applicable += site.collections[collection_name].docs
else
# logger not installed
# Jekyll.logger.warn "AnyAt: Collection '#{collection_name}' not found, skipping."
end
end
end
for page in combined_applicable
next unless page.content
# Apply the transformation to the content
page.content = process_anyat(page.content, config)
end
end
private
def process_anyat(input, config)
return input unless input.is_a?(String)
# Optional ! for no conversion (use double bang to show how to use bang)
# optional = or $ for raw link or raw username
# platform@username@domain
# or platform@username with domain N/A or default domain
# Example: twitter@user, email@john@example.com
pattern = /(?<noconvert>!?[=$]?)(?<platform>[a-z0-9\-]+)@(?<username>[a-zA-Z0-9_\.\-]*[a-zA-Z0-9_\-])(?:@(?<domain>[a-zA-Z0-9\.\-]*[a-zA-Z0-9\-]))?(?=\W|$)/
linkers = config['linkers'] || {}
return input.gsub(pattern) do |match|
noconvert = $~[:noconvert] || ''
if noconvert && noconvert[0] == '!'
# If the match starts with '!', do not convert
# Remove the '!' and hand back the raw text
match_text = "#{$~[:noconvert][1..-1]}#{$~[:platform]}@#{$~[:username]}"
if $~[:domain]
match_text += "@#{$~[:domain]}"
end
next match_text
end
platform = $~[:platform]
username = $~[:username]
domain = $~[:domain]
unless linkers.key?(platform)
next "#{match} ^%^ Platform not supported ^%^"
end
# Platform info - resolve aliases
pi = linkers[platform]
n=[]
while pi.is_a?(String)
if n.include?(pi)
next "#{match} ^%^ Circular alias detected for '#{platform}' ^%^"
end
n << pi
alias_target = pi.downcase.gsub(/[^a-z0-9\-]/, '') # Normalize alias target
if linkers.key?(alias_target)
pi = linkers[alias_target]
else
next "#{match} ^%^ Alias target '#{alias_target}' not found ^%^"
end
end
# Substitutions
if domain && !domain.empty?
url = (pi[ 'link_domain' ] || pi[ 'link' ]).gsub('^u', username).gsub('^d', domain)
text = (pi['format_domain'] || pi['format']).gsub('^u', username).gsub('^d', domain)
elsif pi['domain']
domain = pi['domain']
url = (pi[ 'link' ] || pi[ 'link_domain' ]).gsub('^u', username).gsub('^d', domain)
text = (pi['format'] || pi['format_domain']).gsub('^u', username).gsub('^d', domain)
else
url = pi[ 'link' ].gsub('^u', username)
text = pi['format'].gsub('^u', username)
end
if noconvert && noconvert[-1] == '='
next url
elsif noconvert && noconvert[-1] == '$'
next text
end
# Link to url
next "<a href=\"#{url}\" class=\"anyat_badge badge-#{platform}\" target=\"_blank\">#{pi['badge']} #{text}</a>"
end
end
end
end

View file

@ -308,3 +308,16 @@ button:active {
.news-item { .news-item {
} }
.anyat_badge {
display:inline-block;
width:fit-content;
border: 2px solid var(--fg-lighter);
background-color: var(--fg);
border-radius: 8px;
padding: 0 4px;
}
.anyat_badge:hover {
/* border-color: var(--a-color); */
color: var(--t-color);
}

View file

@ -20,14 +20,14 @@ If you do qualify, you can ask for personal and/or tech accounts
## Registration ## Registration
In order to register, please send us an email to account@linuxposting.xyz. We will save this address in order to contact you about your account(s). We also recommend you share a second email address with us, in case you lose access to the first one In order to register, please send us an email to email@account@linuxposting.xyz. We will save this address in order to contact you about your account(s). We also recommend you share a second email address with us, in case you lose access to the first one
This is how we want you to share this data with us. You can duplicate keys if you want multiple accounts, or skip them if you don't want one. The arrows explain what each key is for. Feel free to copy and paste this This is how we want you to share this data with us. You can duplicate keys if you want multiple accounts, or skip them if you don't want one. The arrows explain what each key is for. Feel free to copy and paste this
> contact: email@example.com <-- second email that you can contact us from. for example, if you ever need to get a password reset > contact: !email@example.com <-- second email that you can contact us from. for example, if you ever need to get a password reset
> email: username > email: username
> matrix: username > matrix: username
> wafrn: email@example.com <-- email that you'll be registering with on w.linuxposting.xyz > wafrn: !email@example.com <-- email that you'll be registering with on w.linuxposting.xyz
## Response ## Response
@ -45,16 +45,16 @@ Molly the Example Mouse [image of her] would like some accounts.
She sends an email as follows: She sends an email as follows:
> FROM: molly@example.com TO: account@linuxposting.xyz > FROM: email@molly@example.com TO: email@account@linuxposting.xyz
> SUBJECT: Accounts > SUBJECT: Accounts
> > hi, i'm molly and I'd like some accounts on your website please > > hi, i'm molly and I'd like some accounts on your website please
> > > >
> > email: molly@linuxposting.xyz > > email: !molly@linuxposting.xyz
> > wafrn: molly-the-example-mouse > > wafrn: molly-the-example-mouse
> > wafrn: baloo-file-official > > wafrn: baloo-file-official
> > > >
> > thank you! > > thank you!
It is then verified that she runs the @baloo-file-official tumblr account, and she recieves the accounts requested. Notice that she didn't add a contact field. This is because she didn't have another email. It is then verified that she runs the @baloo-file-official tumblr account, and she receives the accounts requested. Notice that she didn't add a contact field. This is because she didn't have another email.