awfulirc

package module
v0.0.0-...-1f3aaf7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 3, 2026 License: MIT Imports: 27 Imported by: 0

README

awfulirc

Username and password authentication

The fastest way to get started is to run the server with username and password:

awfulirc --username "Your username" --password "Your password"

Then, connect to the bridge with your favorite IRC client:

/CONNECT 127.0.0.1 6667

Token authentication

If you are paranoid about your credentials leaking, you can use token authentication as well. First generate a token with gen-token.sh. Instead of passing in username and password to awfulirc, pass the token file:

awfulirc --authfile ~/.sa-login

Then, connect to the bridge with your favorite IRC client:

/CONNECT 127.0.0.1 6667

Documentation

Overview

Package awfulirc implements a local IRC bridge for interacting with somethingawful.com. There is no security at all. Do not host this on a publicly accessible port.

See cmd/awfulirc for the IRC bridge binary.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrMessageTooLong    = errors.New("message too long")
	ErrPrefixOnlyMessage = errors.New("message only contains prefix")
	ErrEmptyCommand      = errors.New("message does not contain command")
)
View Source
var WellKnownThreads = []ThreadMetadata{
	{
		ID:    4103011,
		Title: "awfulirc help and discussion",
		Hint:  "awfulirc",
	},
	{
		ID:    4055683,
		Title: "Legends - PYF SA Legends",
		Hint:  "legends",
	},
	{
		ID:    4083561,
		Title: "[L@@K] The thread where you can see when threads are opened in SAD",
		Hint:  "sad",
	},
}

WellKnownThreads contains a manual listing of threads with canonical names that will be reserved before additional bookmarks are processed.

The Hint can be any string, and does not even need to be unique, but is most useful if it is a short unique string that will form the channel name.

Functions

func AuthorToIRC

func AuthorToIRC(author string) string

AuthorToIRC returns the IRC-normalized author name.

func IRCToAuthor

func IRCToAuthor(irc string) string

IRCToAuthor inverts the IRC-normalized author name into the forum name.

func MessageToIRC

func MessageToIRC(author, ch, body string) []string

MessageToIRC converts a post into a sequence of PRIVMSG messages that respect IRC limits.

func NewClientMessageIterator

func NewClientMessageIterator(r io.Reader) func(yield func(*ClientMessage, error) bool)

NewClientMessageIterator iterates the raw client stream and returns a sequence of parsed IRC commands.

func NormalizePost

func NormalizePost(post *html.Node) string

NormalizePost converts a node that wraps a post into an IRC-friendly string. This function is not responsible for converting the string into IRC-delimited lines.

func ParseNetscapeCookieFile

func ParseNetscapeCookieFile(r io.Reader, jar http.CookieJar) error

Types

type AwfulClient

type AwfulClient struct {
	// contains filtered or unexported fields
}

AwfulClient accesses and parses somethingawful.com.

func NewAwfulClient

func NewAwfulClient() (*AwfulClient, error)

NewAwfulClient returns an empty client that has not been logged in yet. Some operations should work without logging in, but that flow has not been tested much, so you probably want to Login immediately after construction. As an alterantive to passing plaintext credentials to the client, you can first get cookies and then set the auth from the cookies file. See README.md.

func (*AwfulClient) Login

func (a *AwfulClient) Login(ctx context.Context, username, password string) error

Login logs in with the given credentials.

func (*AwfulClient) ParseAllBookmarks

func (a *AwfulClient) ParseAllBookmarks(ctx context.Context) ([]ThreadMetadata, error)

ParseAllBookmarks iterates all bookmarked threads and returns them.

func (*AwfulClient) ParseForumThreads

func (a *AwfulClient) ParseForumThreads(ctx context.Context, forumid int) ([]ThreadMetadata, error)

func (*AwfulClient) ParseLastThreadPosts

func (a *AwfulClient) ParseLastThreadPosts(ctx context.Context, thread ThreadMetadata) (Posts, error)

ParseLastThreadPosts returns all posts on the last page of the thread.

func (*AwfulClient) ParseLepersColony

func (a *AwfulClient) ParseLepersColony(ctx context.Context) (*Posts, error)

ParseLepersColony returns the lepers colony formatted as a sequence of posts.

func (*AwfulClient) ParsePagePosts

func (a *AwfulClient) ParsePagePosts(ctx context.Context, thread ThreadMetadata, page int) (Posts, error)

ParsePagePosts returns all posts on the specific page of the thread.

func (*AwfulClient) ParsePrivateMessages

func (a *AwfulClient) ParsePrivateMessages(ctx context.Context) ([]PrivateMessageMetadata, error)

ParsePrivateMessages returns all inbox messages.

func (*AwfulClient) ParseRecentBookmarks

func (a *AwfulClient) ParseRecentBookmarks(ctx context.Context) ([]ThreadMetadata, error)

ParseRecentBookmarks parses recently updated bookmarked threads and returns them.

func (*AwfulClient) ParseUnreadPosts

func (a *AwfulClient) ParseUnreadPosts(ctx context.Context, thread ThreadMetadata) (Posts, error)

ParseUnreadPosts returns all posts on the last unread page. Note that the client doesn't track previously seen posts, so this may duplicate if called twice and the page hasn't changed.

func (*AwfulClient) ReplyToThread

func (a *AwfulClient) ReplyToThread(ctx context.Context, thread ThreadMetadata, message string) error

ReplyToThread replies to the given thread with the given message.

func (*AwfulClient) SendPrivateMessage

func (a *AwfulClient) SendPrivateMessage(ctx context.Context, to, title, message string) error

SendPrivateMessage composes a private message to the given user. The user must be specified as a forum login, not as a normalized IRC name.

func (*AwfulClient) SetAuthCookies

func (a *AwfulClient) SetAuthCookies(r io.Reader) error

type ClientMessage

type ClientMessage struct {
	// Prefix is the optional message prefix. The colon prefix is not
	// included in this string.
	Prefix string

	// RawCommand is the command provided by the client.
	RawCommand string

	// Command is the parsed command from the client, or
	// Command_Unknown if it cannot be parsed.
	Command

	// Parameters contains all command parameters, including the
	// trailing parameter as the last element of the slice.
	Parameters []string
}

ClientMessage is a parsed message from the connected client.

func ParseSingleClientMessage

func ParseSingleClientMessage(msg []byte) (*ClientMessage, error)

ParseSingleClientMessage parses a message from a single IRC line. The CR LF delimiter must have been removed.

type Command

type Command int
const (
	Command_Unknown Command = iota
	Command_Pass
	Command_Nick
	Command_User
	Command_Server
	Command_Oper
	Command_Quit
	Command_Squit
	Command_Join
	Command_Part
	Command_Mode
	Command_Topic
	Command_Names
	Command_List
	Command_Invite
	Command_Kick
	Command_Version
	Command_Stats
	Command_Links
	Command_Time
	Command_Connect
	Command_Trace
	Command_Admin
	Command_Info
	Command_Privmsg
	Command_Notice
	Command_Who
	Command_Whois
	Command_Whowas
	Command_Kill
	Command_Ping
	Command_Pong
	Command_Error
	Command_Cap
	Command_Ison
)

type LimitedHTTPClient

type LimitedHTTPClient struct {
	// contains filtered or unexported fields
}

LimitedHTTPClient performs throttled requests to somethingawful.com. The zero value is not valid for use.

func NewLimitedHTTPClient

func NewLimitedHTTPClient() (*LimitedHTTPClient, error)

NewLimitedHTTPClient returns a rate limited client with a cookie jar configured.

func (*LimitedHTTPClient) Do

func (c *LimitedHTTPClient) Do(req *http.Request) (*http.Response, error)

Do waits until the client is within rate limits and then performs the request.

type Post

type Post struct {
	// ID is the unique post ID from somethingawul.com.
	ID int64

	// Author is the raw author name.
	Author string

	// Body is the raw body text.
	Body string
}

Post contains the raw post.

type Posts

type Posts struct {
	Posts       []Post
	CurrentPage int64
	TotalPages  int64
}

Posts contains all posts on a thread page.

type PrivateMessageMetadata

type PrivateMessageMetadata struct {
	ID     int64
	Author string
	Time   time.Time
}

PrivateMessageMetadata represents a listing in the PM inbox.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the IRC bridge. The server scans bookmarks and periodically polls threads for new messages, sending those to connected clients. All connected clients are treated as if they are logged in as the server's credentials. Client messages in a thread channel will post to that thread.

func Listen

func Listen(ctx context.Context, client *AwfulClient, name, addr string) (*Server, error)

Listen starts an IRC bridge with the given somethingawful.com credentials, IRC server name, and listen address. The address is usually 127.0.0.1:<port>. Use non-local IP masks at your peril.

type ThreadMetadata

type ThreadMetadata struct {
	// ID is the somethingawful.com thread ID.
	ID int64

	// Title is the thread title, which may change regularly.
	Title string

	// Author is the original author of the thread.
	Author string

	// Replies is the number of replies in the thread.
	Replies int64

	// Updated is the last thread update time.
	Updated time.Time

	// KilledBy is the last poster of the thread.
	KilledBy string

	// Hint is a manually specified short name hint. See
	// well_known_threads.go for hard-coded threads with hints based
	// on canonical names.
	Hint string
}

ThreadMetadata represents a thread without its posts.

func (ThreadMetadata) LastPostURL

func (t ThreadMetadata) LastPostURL() string

LastPostURL returns the URL to the thread's last post page.

func (ThreadMetadata) PageURL

func (t ThreadMetadata) PageURL(p int) string

PageURL returns the URL to the specific page of the thread.

func (ThreadMetadata) ReplyURL

func (t ThreadMetadata) ReplyURL() string

ReplyURL returns the URL to the reply page of the thread.

func (ThreadMetadata) UnreadPostURL

func (t ThreadMetadata) UnreadPostURL() string

UnreadPostURL returns the URL to the thread's last unread post.

Directories

Path Synopsis
cmd
awfulirc command
Runs the awfulirc bridge.
Runs the awfulirc bridge.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL