Merge branch 'develop'
@@ -13,6 +13,5 @@
|
|||||||
<classpathentry kind="lib" path="lib/slf4j-jdk14-1.7.25.jar"/>
|
<classpathentry kind="lib" path="lib/slf4j-jdk14-1.7.25.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/twitter4j-core-4.0.7-javadoc.jar"/>
|
<classpathentry kind="lib" path="lib/twitter4j-core-4.0.7-javadoc.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/twitter4j-core-4.0.7.jar"/>
|
<classpathentry kind="lib" path="lib/twitter4j-core-4.0.7.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/ini4j-0.5.4.jar"/>
|
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
BSD 3-Clause License
|
BSD 3-Clause License
|
||||||
|
|
||||||
Copyright (c) 2019, AlexStewartCode
|
Copyright (c) 2019, AlexStewartCode and individual contributors.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -1,2 +1,6 @@
|
|||||||
# KittyBot
|
# KittyBot
|
||||||
Fun and useful Discord bot
|
Fun and useful Discord bot designed to be able searching websites, playing games, compiling code, and much more!
|
||||||
|
|
||||||
|
This repo is an eclipse project, and can be opened in the IDE directly. Authentication keys will need to be placed in a file called `Ref.java` at `src/offline/`. This folder isn't present in this repository by default.
|
||||||
|
|
||||||
|
If you're looking to contribute, feel free to submit a pull request! Take a look at the styleguide to get some pointers on formatting for this repo!
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# KittyBot Style Guide
|
||||||
|
|
||||||
|
This document represents the reasonable defaults and expectations for this project, and provides some rationale for the style restrictions! There can always be exceptions to the rules, but they may need justifying.
|
||||||
|
|
||||||
|
Code Formatting
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Indenting
|
||||||
|
Tabs are used so that individual developers can configure their own indent width settings that won't be enforced on others working on the project.
|
||||||
|
|
||||||
|
```java
|
||||||
|
// I'm not indented!
|
||||||
|
{
|
||||||
|
// I'm indented with one tab!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Braces
|
||||||
|
When braces are present, Allman style is used meaning that braces start on the next line. Braces are used to prevent scope confusion. Omitting braces on single-line statements is fine if the situation is clear.
|
||||||
|
|
||||||
|
```java
|
||||||
|
if(foo)
|
||||||
|
{
|
||||||
|
System.out.println("This");
|
||||||
|
System.out.println("has");
|
||||||
|
System.out.println("braces!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bar)
|
||||||
|
System.out.println("No braces!");
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Naming
|
||||||
|
Class names and function names are `PascalCase`. Variable names are `camelCase`.
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class MyClass
|
||||||
|
{
|
||||||
|
private Foo myVariable;
|
||||||
|
|
||||||
|
public function MyFuction()
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Favor a broad to narrow naming scheme to promote autocomplete grouping. For example, use a name like `userDescriptionHeader` instead of `headerUserDescription` because there may be other variables related to a user or description, but there's likely only one header section of a description.
|
||||||
|
|
||||||
|
|
||||||
|
#### Ternary Operator (`?:`)
|
||||||
|
Don't.
|
||||||
|
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Commands
|
||||||
|
All commands get spawned on their own threads, and should be implemented in a thread-safe way. Commands all derive from the Command.java class, and use the custom types defined in KittyBot. In order to make any later changes easier and decouple the command logic from core and routing, no JDA structures should be directly exposed in commands, and instead everything needed should be added to the kitty structures that add space to the system. Commands should override the `HelpText` and `Run` functions. Commands are registered in the ObjectBuilderFactory, and the command registration structure can be used for sub-commands as needed. See the RPG for an example.
|
||||||
|
|
||||||
|
#### Tracked Values
|
||||||
|
Does something need to be tracked in a database? Make sure the class with the data you want inherits from DatabaseTrackedObject, and override the appropriate functions. The object, when marked as dirty, will automatically be written to the database when the next database upkeep tick occurs. Refer to CommandBoop to see an example of a tracked global value, and KittyUser for tracked per-user values.
|
||||||
|
|
||||||
|
#### Tokens, Secrets, etc
|
||||||
|
Things like tokens, private keys, an secrets are kept in the offline package. This file is intentionally excluded from the repo. If it shouldn't be in the repo, put it in the offline package.
|
||||||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 60 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
indicator=1
|
||||||
|
boop=1
|
||||||
|
tony, stark, dontfeelgood, dontfeelsogood=1
|
||||||
|
yeet=1
|
||||||
|
role=1
|
||||||
|
ping=1
|
||||||
|
rating=1
|
||||||
|
roll=1
|
||||||
|
blur=1
|
||||||
|
choose=1
|
||||||
|
poll=1
|
||||||
|
rpstart=1
|
||||||
|
bet=1
|
||||||
|
perish, thenperish=1
|
||||||
|
teey=1
|
||||||
|
stats=1
|
||||||
|
beans=1
|
||||||
|
eightball, 8ball=1
|
||||||
|
vote=1
|
||||||
|
results=1
|
||||||
|
wolfram=1
|
||||||
|
map=1
|
||||||
|
info, about=1
|
||||||
|
givebeans=1
|
||||||
|
c++, g++, cplus, cpp=1
|
||||||
|
work=1
|
||||||
|
showpoll=1
|
||||||
|
rpend=1
|
||||||
|
rpg=1
|
||||||
|
tweet=1
|
||||||
|
java, jdoodle=1
|
||||||
|
help=1
|
||||||
|
buildHelp=1
|
||||||
|
invite=1
|
||||||
|
shutdown=1
|
||||||
|
addguildrole=1
|
||||||
|
allowedguildrole=1
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
[ObjectBuilderFactory]
|
||||||
|
indicator=
|
||||||
|
boop=
|
||||||
|
tony, stark, dontfeelgood, dontfeelsogood=
|
||||||
|
yeet=
|
||||||
|
role=
|
||||||
|
ping=
|
||||||
|
rating=
|
||||||
|
roll=
|
||||||
|
blur=
|
||||||
|
choose=
|
||||||
|
poll=
|
||||||
|
rpstart=
|
||||||
|
bet=
|
||||||
|
addguildrole=
|
||||||
|
perish, thenperish=
|
||||||
|
teey=
|
||||||
|
stats=
|
||||||
|
allowedguildrole=
|
||||||
|
beans=
|
||||||
|
eightball, 8ball=
|
||||||
|
vote=
|
||||||
|
results=
|
||||||
|
wolfram=
|
||||||
|
map=
|
||||||
|
info, about=
|
||||||
|
givebeans=
|
||||||
|
c++, g++, cplus, cpp=
|
||||||
|
work=
|
||||||
|
showpoll=
|
||||||
|
rpend=
|
||||||
|
rpg=
|
||||||
|
tweet=
|
||||||
|
java, jdoodle=
|
||||||
|
help=
|
||||||
|
buildHelp=
|
||||||
|
invite=
|
||||||
|
shutdown=
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
[CommandPollManage]
|
||||||
|
PollManageInfo='start' will start a new poll with the query of the line you put after, 'choice' will add a choice to the poll, 'stop' will end the poll
|
||||||
|
|
||||||
|
[CommandBeansShow]
|
||||||
|
BeansShowDisplay=You have %s beans!
|
||||||
|
BeansShowInfo=Displays how many beans you have
|
||||||
|
|
||||||
|
[CommandHelp]
|
||||||
|
HelpInfo=Lets you look up specific commands, or get a link to a list of all commands.
|
||||||
|
HelpDisplay=You can get help with a specific command by typing `!help command`!\nGeneral Commands: `boop, roll, choose, help, info, vote, results, showpoll, wolfram, cplus, java, beans, role, bet, yeet`
|
||||||
|
|
||||||
|
[CommandRoll]
|
||||||
|
RollError=Didn't work ;3;
|
||||||
|
RollInfo=Based on input of xdy where x is number of dice and y is faces kitty will roll that amount of dice, display the individual rolls and total
|
||||||
|
|
||||||
|
[CommandStats]
|
||||||
|
StatsInfo=Displays the actively running KittyBot application information
|
||||||
|
|
||||||
|
[CommandTweet]
|
||||||
|
TweetInfo=Kitty will tweet to her personal twitter account
|
||||||
|
TweetError=Tweet command failed!
|
||||||
|
|
||||||
|
[CommandRole]
|
||||||
|
RoleInfo=Will show the current role you have, Admins can change others roles with input of 'role x @y' with x being blacklist, general, mod, or admin. Blacklist will not allow the user to interact with kitty anymore, general mod and admin will give the user access to those commands.
|
||||||
|
RoleStandardResponse=Your role is
|
||||||
|
RoleError=You aren't allowed to do that! You must have the KittyRole '%' or higher!
|
||||||
|
RoleChanged=Changed %s to role `%s`!
|
||||||
|
RoleNeededRole=Please enter `general`, `mod`, or `admin`!
|
||||||
|
|
||||||
|
[CommandColiru]
|
||||||
|
ColiruError=Please provide some c++ code to attempt to compile!
|
||||||
|
ColiruInfo=Will try to compile any c++ code you put in! Supports up to C++14 standard, uses g++.
|
||||||
|
|
||||||
|
[CommandJDoodle]
|
||||||
|
JDoodleInfo=Will compile any java code you put in! Supports Java 1.8
|
||||||
|
JDoodleError=Please provide some java code to get it compiled!
|
||||||
|
|
||||||
|
[CommandChangeIndicator]
|
||||||
|
ChangeIndicatorInfo=Changes the command indicator to any single character. By default, it's '!'. If more than one character is provided, the first one is used!
|
||||||
|
ChangeIndicatorError=Please specify a letter or symbol to use!
|
||||||
|
ChangeIndicatorChanged=Indicator changed to `%s`
|
||||||
|
|
||||||
|
[CommandPerish]
|
||||||
|
PerishInfo=Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned
|
||||||
|
|
||||||
|
[CommandStark]
|
||||||
|
StarkInfo=Snaps your icon or the icon of a friend you mentioned
|
||||||
|
|
||||||
|
[CommandYeet]
|
||||||
|
YeetInfo=Yeet yourself or yeet a friend with @!
|
||||||
|
|
||||||
|
[CommandAllowedGuildRole]
|
||||||
|
AllowedGuildRoleInfo=
|
||||||
|
AllowedGuildRoleDuplicate=Can't add the same role twice!
|
||||||
|
AllowedGuildRoleSuccess=Added %s to the allowed roles!
|
||||||
|
|
||||||
|
[CommandPollVote]
|
||||||
|
PollVoteNotValidNumber=That's not a vaild number!
|
||||||
|
PollVoteInfo=Vote in a poll with the choice number, won't work if no poll is running, you can't change your vote once you have cast it! Be careful!
|
||||||
|
PollVoteNoPoll=There is no poll running!
|
||||||
|
PollVoteAlreadyVoted=You already voted
|
||||||
|
PollVoteNotValidVote=%s That's not a vaild vote!
|
||||||
|
PollVoteSuccess=You successfully voted for
|
||||||
|
|
||||||
|
[CommandShutdown]
|
||||||
|
ShutdownInfo=Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown.
|
||||||
|
|
||||||
|
[CommandTeey]
|
||||||
|
TeeyInfo=Teey yourself back into existance, or teey a friend with @!
|
||||||
|
|
||||||
|
[CommandBetBeans]
|
||||||
|
BetBeansLowBet=Please bet with at least 50 beans!
|
||||||
|
BetBeansInfo=Allows you to bet your beans, set your amount after the command! Warning! House always wins!\nSets of 3 will get 2x, 4 will get 10x, and 5 will get 1000x
|
||||||
|
BetBeansNotValid=That's not a valid bet!
|
||||||
|
BetBeansLose=Sorry, you didn't win, try again!
|
||||||
|
BetBeansNotEnough=You don't have enough beans!
|
||||||
|
BetBeansWin=You won %s beans!
|
||||||
|
|
||||||
|
[CommandDoWork]
|
||||||
|
DoWorkFinished=I finished with my work! :D
|
||||||
|
DoWorkInfo=Occupies a core for a few seconds
|
||||||
|
|
||||||
|
[CommandRPStart]
|
||||||
|
RPStartInfo=Starts an rp, add people to it by mentioning them!
|
||||||
|
|
||||||
|
[CommandBlurry]
|
||||||
|
BlurryInfo=Blurs your icon or the icon of a friend you mentioned
|
||||||
|
|
||||||
|
[CommandPollResults]
|
||||||
|
PollResultsResponse=%s people voted for %s `%s` with `%s%` !\n
|
||||||
|
PollResultsInfo=Will show current results of a poll and percentages of votes per choice
|
||||||
|
|
||||||
|
[CommandRating]
|
||||||
|
RatingInfo='0' is fully sfw (Derpi and e621 searches are disabled), '1' is filtered (kitty auto appends a sfw tag on any searches), '2' is nsfw (any search will go through). Some other words are supported for setting filter as well.
|
||||||
|
RatingWarning=Warning: NSFW may slip through, images are only based on tags on their respective sites!
|
||||||
|
RatingChanged=Kittybot content set to
|
||||||
|
RatingInvalid=Invalid content rating
|
||||||
|
|
||||||
|
[CommandGiveBeans]
|
||||||
|
GiveBeansNoneMentioned=You didn't mention anyone!
|
||||||
|
GiveBeansSuccess=Gave %s %s beans!
|
||||||
|
GiveBeansInvalid=That's not a valid number!
|
||||||
|
GiveBeansInfo=Gives beans to the mentioned users!
|
||||||
|
|
||||||
|
[CommandPollShow]
|
||||||
|
PollShowNoPoll=There is no poll running!
|
||||||
|
PollShowInfo=Will show the current poll running
|
||||||
|
PollShowPoll=The current poll is `%s`\n
|
||||||
|
PollShowChoices=And the choices are:\n
|
||||||
|
|
||||||
|
[CommandHelpBuilder]
|
||||||
|
HelpBuilderInfo=Emit help for all commands as formatted HTML
|
||||||
|
|
||||||
|
[CommandRPEnd]
|
||||||
|
RPEndError=You can't end this RP!
|
||||||
|
RPEndInfo=Ends RP in channel and gives you a .txt file!
|
||||||
|
RPEndFileOut=Here's your file!
|
||||||
|
|
||||||
|
[CommandRPG]
|
||||||
|
RPGInfo=Admin+ command only right now - experimental text RPG! Format is !rpg <rpg command>
|
||||||
|
RPGInvalid=Invalid RPG Command!
|
||||||
|
|
||||||
|
[CommandBoop]
|
||||||
|
BoopPerson=%s booped %s!
|
||||||
|
BoopInfo=Kitty will react with a counter
|
||||||
|
BoopStandard=Woah! %s booped me! That's %s total!
|
||||||
|
BoopMultiple=%s booped several others - %s!
|
||||||
|
|
||||||
|
[CommandInfo]
|
||||||
|
InfoResponse=I'm made by `Rin#8904` and `Reverie Wisp#3703`!\nYou can find more info about me along with a Patreon link to support us and GitHub link for filing bugs https://www.rinsnowmew.com/bot/
|
||||||
|
InfoInfo=Provides author info and a link to Kitty's website
|
||||||
|
|
||||||
|
[CommandPing]
|
||||||
|
PingResponse=Pong!
|
||||||
|
PingInfo=Will respond with Pong!
|
||||||
|
|
||||||
|
[CommandChoose]
|
||||||
|
ChooseChoice=I chooooooose %s!
|
||||||
|
ChooseOne=I can't choose from *one* thing!
|
||||||
|
ChooseInfo=With an input of x,y,z where x y and z are all choices, kitty will choose one
|
||||||
|
|
||||||
|
[CommandEightBall]
|
||||||
|
EightBallYes4=Yes - definitely.
|
||||||
|
EightBallYes3=Without a doubt.
|
||||||
|
EightBallYes2=It is decidedly so.
|
||||||
|
EightBallYes1=It is certain.
|
||||||
|
EightBallYes8=Outlook good.
|
||||||
|
EightBallYes7=Most likely.
|
||||||
|
EightBallYes6=As I see it, yes.
|
||||||
|
EightBallYes5=You may rely on it.
|
||||||
|
EightBallMaybe1=Reply hazy, try again.
|
||||||
|
EightBallMaybe2=Ask again later.
|
||||||
|
EightBallError=Hmm? You'll need to ask a question!
|
||||||
|
EightBallMaybe3=Better not tell you now.
|
||||||
|
EightBallMaybe4=Cannot predict now.
|
||||||
|
EightBallMaybe5=Concentrate and ask again.
|
||||||
|
EightBallInfo=Answers a yes or no question! Warning: Kitty can not actually tell the future, she claims no responsibility for any lion mauling, lack of lottery wins, or felony charges.
|
||||||
|
EightBallNo5=Very doubtful.
|
||||||
|
EightBallNo3=My sources say no.
|
||||||
|
EightBallNo4=Outlook not so good.
|
||||||
|
EightBallNo1=Don't count on it.
|
||||||
|
EightBallNo2=My reply is no.
|
||||||
|
EightBallYes9=Yes.
|
||||||
|
EightBallYes10=Signs point to yes.
|
||||||
|
|
||||||
|
[CommandInvite]
|
||||||
|
InviteInfo=Provides a direct invite link for KittyBot
|
||||||
|
|
||||||
|
[CommandWolfram]
|
||||||
|
WolframError=Something went wrong!
|
||||||
|
WolframInfo=Will query wolframalpha with your question and give a full image output of the answer
|
||||||
|
WolframNoArgs=You need to provide some arguments!
|
||||||
|
|
||||||
|
[CommandAddGuildRole]
|
||||||
|
AddGuildRoleInfo=Add a role to yourself!
|
||||||
|
AddGuildRoleNotAllowed=You are not allowed to add %s!
|
||||||
|
AddGuildRoleSuccess=Added %s to %s
|
||||||
|
AddGuildRoleFailure=Failed to add %s to %s
|
||||||
|
|
||||||
|
[CommandMap]
|
||||||
|
MapInfo=Generates a map! You can pass additional information if you want with the flags `-s<seed>-w<width>-h<height>`. If one of the fields isn't provided, its default will be used. Note that adjusting the width and height impacts the map outcomes.\n\nDefault seed: Random,\nDefault Width: 35(max %s),\nDefault Height: 25(max %s)
|
||||||
|
MapSeed=Seed
|
||||||
|
MapInvalid=Invalid arguments provided!
|
||||||
|
MapVersion=Using mapgen v0.1
|
||||||
|
MapWidth=Width
|
||||||
|
MapHeight=Height
|
||||||
|
|
||||||
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
[CommandBeansShow]
|
|
||||||
Displays how many beans you have =
|
|
||||||
You have %s beans! =
|
|
||||||
|
|
||||||
[CommandBetBeans]
|
|
||||||
Please bet with at least 50 beans! =
|
|
||||||
Allows you to bet your beans, set your amount after the command! Warning! House always wins!\nSets of 3 will get 5x, 4 will get 10x, and 5 will get 1000x =
|
|
||||||
That's not a valid bet! =
|
|
||||||
Sorry, you didn't win, try again! =
|
|
||||||
You don't have enough beans! =
|
|
||||||
You won %s beans! =
|
|
||||||
|
|
||||||
[CommandBoop]
|
|
||||||
%s booped %s! =
|
|
||||||
Kitty will react with a counter =
|
|
||||||
Woah! %s booped me! That's %s total! =
|
|
||||||
%s booped several others - %s! =
|
|
||||||
|
|
||||||
[CommandBlurry]
|
|
||||||
Blurs your icon or the icon of a friend you mentioned =
|
|
||||||
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package commands;
|
||||||
|
|
||||||
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
|
import dataStructures.KittyChannel;
|
||||||
|
import dataStructures.KittyGuild;
|
||||||
|
import dataStructures.KittyRating;
|
||||||
|
import dataStructures.KittyRole;
|
||||||
|
import dataStructures.KittyUser;
|
||||||
|
import dataStructures.Response;
|
||||||
|
import dataStructures.UserInput;
|
||||||
|
|
||||||
|
public class CommandAddGuildRole extends Command
|
||||||
|
{
|
||||||
|
public CommandAddGuildRole(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String HelpText() { return LocStrings.Stub("AddGuildRoleInfo"); };
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
|
{
|
||||||
|
String role = input.args.split(" ")[0];
|
||||||
|
if(guild.allowedRole.contains(role))
|
||||||
|
{
|
||||||
|
if(guild.control.addRole(user.discordID, role))
|
||||||
|
{
|
||||||
|
res.Call(String.format(LocStrings.Stub("AddGuildRoleSuccess"), role, user.name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.Call(String.format(LocStrings.Stub("AddGuildRoleFailure"), role, user.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.Call(String.format(LocStrings.Stub("AddGuildRoleNotAllowed"), role));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package commands;
|
||||||
|
|
||||||
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
|
import dataStructures.KittyChannel;
|
||||||
|
import dataStructures.KittyGuild;
|
||||||
|
import dataStructures.KittyRating;
|
||||||
|
import dataStructures.KittyRole;
|
||||||
|
import dataStructures.KittyUser;
|
||||||
|
import dataStructures.Response;
|
||||||
|
import dataStructures.UserInput;
|
||||||
|
|
||||||
|
public class CommandAllowedGuildRole extends Command
|
||||||
|
{
|
||||||
|
public CommandAllowedGuildRole(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String HelpText() { return LocStrings.Stub("AllowedGuildRoleInfo"); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
|
{
|
||||||
|
String [] roles = input.args.split(",");
|
||||||
|
String role;
|
||||||
|
for(int i = 0; i < roles.length; i++)
|
||||||
|
{
|
||||||
|
role = roles[i].trim();
|
||||||
|
if(guild.allowedRole.contains(role))
|
||||||
|
{
|
||||||
|
res.Call(LocStrings.Stub("AllowedGuildRoleDuplicate"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
guild.allowedRole.add(role);
|
||||||
|
res.Call(String.format(LocStrings.Stub("AllowedGuildRoleSuccess"), role));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
import core.Localizer;
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
|
|
||||||
public class CommandBeansShow extends Command
|
public class CommandBeansShow extends Command
|
||||||
@@ -9,11 +9,11 @@ public class CommandBeansShow extends Command
|
|||||||
public CommandBeansShow(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandBeansShow(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return Localizer.Stub("Displays how many beans you have"); };
|
public String HelpText() { return LocStrings.Stub("BeansShowInfo"); };
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
res.Call(String.format(Localizer.Stub("You have %s beans!"), user.GetBeans()));
|
res.Call(String.format(LocStrings.Stub("BeansShowDisplay"), user.GetBeans()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
import core.Localizer;
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
|
|
||||||
public class CommandBetBeans extends Command
|
public class CommandBetBeans extends Command
|
||||||
@@ -9,7 +11,7 @@ public class CommandBetBeans extends Command
|
|||||||
public CommandBetBeans(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandBetBeans(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return Localizer.Stub("Allows you to bet your beans, set your amount after the command! Warning! House always wins!\nSets of 3 will get 5x, 4 will get 10x, and 5 will get 1000x"); }
|
public String HelpText() { return LocStrings.Stub("BetBeansInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -22,19 +24,19 @@ public class CommandBetBeans extends Command
|
|||||||
bet = Integer.parseInt(input.args);
|
bet = Integer.parseInt(input.args);
|
||||||
if(bet < 50)
|
if(bet < 50)
|
||||||
{
|
{
|
||||||
res.Call(Localizer.Stub("Please bet with at least 50 beans!"));
|
res.Call(LocStrings.Stub("BetBeansLowBet"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e)
|
catch (NumberFormatException e)
|
||||||
{
|
{
|
||||||
res.Call(Localizer.Stub("That's not a valid bet!"));
|
res.Call(LocStrings.Stub("BetBeansNotValid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(user.GetBeans() < bet)
|
if(user.GetBeans() < bet)
|
||||||
{
|
{
|
||||||
res.Call(Localizer.Stub("You don't have enough beans!"));
|
res.Call(LocStrings.Stub("BetBeansNotEnough"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,12 +51,12 @@ public class CommandBetBeans extends Command
|
|||||||
|
|
||||||
if(win == 0)
|
if(win == 0)
|
||||||
{
|
{
|
||||||
res.Call(Localizer.Stub("Sorry, you didn't win, try again!"));
|
res.Call(LocStrings.Stub("BetBeansLose"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.ChangeBeans(bet*win);
|
user.ChangeBeans(bet*win);
|
||||||
res.Call(String.format(Localizer.Stub("You won %s beans!"), "" + (bet*win)));
|
res.Call(String.format(LocStrings.Stub("BetBeansWin"), "" + (bet*win)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getWinning(int [] slots)
|
private int getWinning(int [] slots)
|
||||||
@@ -69,7 +71,7 @@ public class CommandBetBeans extends Command
|
|||||||
counter = 1;
|
counter = 1;
|
||||||
|
|
||||||
if(counter == 3)
|
if(counter == 3)
|
||||||
winning = 5;
|
winning = 2;
|
||||||
|
|
||||||
if(counter == 4)
|
if(counter == 4)
|
||||||
winning = 10;
|
winning = 10;
|
||||||
@@ -83,10 +85,12 @@ public class CommandBetBeans extends Command
|
|||||||
|
|
||||||
private int[] getSlots()
|
private int[] getSlots()
|
||||||
{
|
{
|
||||||
|
Random gen = new Random();
|
||||||
int[] nums = new int[5];
|
int[] nums = new int[5];
|
||||||
for (int i = 0; i < nums.length; i++)
|
for (int i = 0; i < nums.length; i++)
|
||||||
{
|
{
|
||||||
nums[i] = (int) (Math.random() * 5) + 1;
|
nums[i] = Math.abs(gen.nextInt() % 7) + 1;
|
||||||
|
System.out.println(nums [i]);
|
||||||
}
|
}
|
||||||
return nums;
|
return nums;
|
||||||
}
|
}
|
||||||
@@ -138,6 +142,12 @@ public class CommandBetBeans extends Command
|
|||||||
case 5:
|
case 5:
|
||||||
slotHearts += ":purple_heart:";
|
slotHearts += ":purple_heart:";
|
||||||
break;
|
break;
|
||||||
|
case 6:
|
||||||
|
slotHearts += ":black_heart:";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
slotHearts += ":broken_heart:";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import java.io.IOException;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
import core.Localizer;
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
import utils.ImageUtils;
|
import utils.ImageUtils;
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ public class CommandBlurry extends Command
|
|||||||
public CommandBlurry(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandBlurry(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return Localizer.Stub("Blurs your icon or the icon of a friend you mentioned"); };
|
public String HelpText() { return LocStrings.Stub("BlurryInfo"); };
|
||||||
|
|
||||||
private static Long num = 0l;
|
private static Long num = 0l;
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class CommandBoop extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return Localizer.Stub("Kitty will react with a counter"); }
|
public String HelpText() { return LocStrings.Stub("BoopInfo"); }
|
||||||
|
|
||||||
// Called when the command is run!
|
// Called when the command is run!
|
||||||
@Override
|
@Override
|
||||||
@@ -69,14 +69,14 @@ public class CommandBoop extends Command
|
|||||||
if(input.mentions == null)
|
if(input.mentions == null)
|
||||||
{
|
{
|
||||||
boopTracker.ApplyBoop();
|
boopTracker.ApplyBoop();
|
||||||
res.Call(String.format(Localizer.Stub("Woah! %s booped me! That's %s total!"), user.name, boopTracker.HowMany()));
|
res.Call(String.format(LocStrings.Stub("BoopStandard"), user.name, boopTracker.HowMany()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(input.mentions.length == 1)
|
if(input.mentions.length == 1)
|
||||||
{
|
{
|
||||||
boopTracker.ApplyBoop();
|
boopTracker.ApplyBoop();
|
||||||
res.Call(String.format(Localizer.Stub("%s booped %s!"), user.name, input.mentions[0].name));
|
res.Call(String.format(LocStrings.Stub("BoopPerson"), user.name, input.mentions[0].name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ public class CommandBoop extends Command
|
|||||||
booped += "and " + input.mentions[i].name;
|
booped += "and " + input.mentions[i].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Call(String.format(Localizer.Stub("%s booped several others - %s!"), user.name, booped));
|
res.Call(String.format(LocStrings.Stub("BoopMultiple"), user.name, booped));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
|
|
||||||
public class CommandChangeIndicator extends Command
|
public class CommandChangeIndicator extends Command
|
||||||
@@ -8,7 +9,7 @@ public class CommandChangeIndicator extends Command
|
|||||||
public CommandChangeIndicator(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandChangeIndicator(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Changes the command indicator to any single character. By default, it's '!'. If more than one character is provided, the first one is used!"; }
|
public String HelpText() { return LocStrings.Stub("ChangeIndicatorInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -16,11 +17,11 @@ public class CommandChangeIndicator extends Command
|
|||||||
String arg = input.args.trim();
|
String arg = input.args.trim();
|
||||||
if(arg.length() == 0)
|
if(arg.length() == 0)
|
||||||
{
|
{
|
||||||
res.Call("Please specify a letter or symbol to use!");
|
res.Call(LocStrings.Stub("ChangeIndicatorError"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
guild.SetCommandIndicator(arg.substring(0, 1));
|
guild.SetCommandIndicator(arg.substring(0, 1));
|
||||||
res.Call("Indicator changed to `" + guild.GetCommandIndicator() +"`!");
|
res.Call(String.format(LocStrings.Stub("ChangeIndicatorChanged"), guild.GetCommandIndicator()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class CommandChoose extends Command
|
|||||||
public CommandChoose(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandChoose(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "With an input of x,y,z where x y and z are all choices, kitty will choose one"; }
|
public String HelpText() { return LocStrings.Stub("ChooseInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -22,10 +22,10 @@ public class CommandChoose extends Command
|
|||||||
String [] choices = input.args.split(",");
|
String [] choices = input.args.split(",");
|
||||||
if(choices.length == 1)
|
if(choices.length == 1)
|
||||||
{
|
{
|
||||||
res.Call("I can't choose from *one* thing!");
|
res.Call(LocStrings.Stub("ChooseOne"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Call("I chooooooose" + choices[(int) (Math.random()*choices.length)] + "!");
|
res.Call(String.format(LocStrings.Stub("ChooseChoice"), (choices[(int) (Math.random()*choices.length)]).toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
import network.NetworkColiru;
|
import network.NetworkColiru;
|
||||||
|
|
||||||
@@ -11,11 +12,17 @@ public class CommandColiru extends Command
|
|||||||
public CommandColiru(KittyRole level, KittyRating rating) { super(level, rating);}
|
public CommandColiru(KittyRole level, KittyRating rating) { super(level, rating);}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Will try to compile any c++ code you put in! Supports up to C++14 standard, uses g++."; }
|
public String HelpText() { return LocStrings.Stub("ColiruInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
|
if(input.args.trim().length() < 1)
|
||||||
|
{
|
||||||
|
res.Call(LocStrings.Stub("ColiruError"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
res.Call(compiler.compileCPlus(input.args));
|
res.Call(compiler.compileCPlus(input.args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class CommandDoWork extends Command
|
|||||||
public CommandDoWork(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandDoWork(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Occupies a core for a few seconds"; }
|
public String HelpText() { return LocStrings.Stub("DoWorkInfo"); }
|
||||||
|
|
||||||
// Called when the command is run!
|
// Called when the command is run!
|
||||||
@Override
|
@Override
|
||||||
@@ -28,6 +28,6 @@ public class CommandDoWork extends Command
|
|||||||
thispieceofshit += Math.log((double)i);
|
thispieceofshit += Math.log((double)i);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Call("I finished with my work! :D");
|
res.Call(LocStrings.Stub("DoWorkFinished"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,48 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
|
|
||||||
public class CommandEightBall extends Command
|
public class CommandEightBall extends Command
|
||||||
{
|
{
|
||||||
String [] answers = {"It is certain.", "It is decidedly so.", "Without a doubt.", "Yes - definitely.", "You may rely on it.", "As I see it, yes.", "Most likely.",
|
String [] answers =
|
||||||
"Outlook good.", "Yes.", "Signs point to yes.", "Reply hazy, try again.", "Ask again later.", "Better not tell you now.", "Cannot predict now.",
|
|
||||||
"Concentrate and ask again.", "Don't count on it.", "My reply is no.", "My sources say no.", "Outlook not so good.", "Very doubtful."};
|
|
||||||
public CommandEightBall(KittyRole level, KittyRating rating)
|
|
||||||
{
|
{
|
||||||
super(level, rating);
|
LocStrings.Stub("EightBallYes1")
|
||||||
}
|
, LocStrings.Stub("EightBallYes2")
|
||||||
|
, LocStrings.Stub("EightBallYes3")
|
||||||
|
, LocStrings.Stub("EightBallYes4")
|
||||||
|
, LocStrings.Stub("EightBallYes5")
|
||||||
|
, LocStrings.Stub("EightBallYes6")
|
||||||
|
, LocStrings.Stub("EightBallYes7")
|
||||||
|
, LocStrings.Stub("EightBallYes8")
|
||||||
|
, LocStrings.Stub("EightBallYes9")
|
||||||
|
, LocStrings.Stub("EightBallYes10")
|
||||||
|
|
||||||
|
, LocStrings.Stub("EightBallMaybe1")
|
||||||
|
, LocStrings.Stub("EightBallMaybe2")
|
||||||
|
, LocStrings.Stub("EightBallMaybe3")
|
||||||
|
, LocStrings.Stub("EightBallMaybe4")
|
||||||
|
, LocStrings.Stub("EightBallMaybe5")
|
||||||
|
|
||||||
|
, LocStrings.Stub("EightBallNo1")
|
||||||
|
, LocStrings.Stub("EightBallNo2")
|
||||||
|
, LocStrings.Stub("EightBallNo3")
|
||||||
|
, LocStrings.Stub("EightBallNo4")
|
||||||
|
, LocStrings.Stub("EightBallNo5")
|
||||||
|
};
|
||||||
|
|
||||||
|
public CommandEightBall(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Answers a yes or no question! Warning: Kitty can not actually tell the future,"
|
public String HelpText() { return LocStrings.Stub("EightBallInfo"); }
|
||||||
+ " she claims no responsibility for any lion mauling, lack of lottery wins, or felony charges."; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
|
if(input.args.trim().length() < 1)
|
||||||
|
res.Call(LocStrings.Stub("EightBallError"));
|
||||||
|
|
||||||
res.Call(answers[(int) (Math.random()*answers.length)]);
|
res.Call(answers[(int) (Math.random()*answers.length)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
|
|
||||||
public class CommandGiveBeans extends Command
|
public class CommandGiveBeans extends Command
|
||||||
@@ -8,7 +9,7 @@ public class CommandGiveBeans extends Command
|
|||||||
public CommandGiveBeans (KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandGiveBeans (KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Gives beans to the mentioned users!"; }
|
public String HelpText() { return LocStrings.Stub("GiveBeansInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -19,20 +20,20 @@ public class CommandGiveBeans extends Command
|
|||||||
}
|
}
|
||||||
catch (NumberFormatException e)
|
catch (NumberFormatException e)
|
||||||
{
|
{
|
||||||
res.Call("That's not a valid number!");
|
res.Call(LocStrings.Stub("GiveBeansInvalid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(input.mentions == null)
|
if(input.mentions == null)
|
||||||
{
|
{
|
||||||
res.Call("You didn't mention anyone!");
|
res.Call(LocStrings.Stub("GiveBeansNoneMentioned"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < input.mentions.length; i++)
|
for(int i = 0; i < input.mentions.length; i++)
|
||||||
{
|
{
|
||||||
input.mentions[i].ChangeBeans(beans);
|
input.mentions[i].ChangeBeans(beans);
|
||||||
res.Call("Gave " + input.mentions[i].name + " " + beans + " beans!");
|
res.Call(String.format(LocStrings.Stub("GiveBeansSuccess"), input.mentions[i].name, "" + beans));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,13 @@ import dataStructures.KittyUser;
|
|||||||
import dataStructures.Response;
|
import dataStructures.Response;
|
||||||
import dataStructures.UserInput;
|
import dataStructures.UserInput;
|
||||||
|
|
||||||
// TODO: Convert this to a per-command help string! This lets us do all sorts of neat stuff,
|
// Either allows for specifically looking up commands or gets a list of general commands to try out!
|
||||||
// mostly tho it lets us construct this on the fly or by hand for a specific command!
|
|
||||||
public class CommandHelp extends Command
|
public class CommandHelp extends Command
|
||||||
{
|
{
|
||||||
public CommandHelp(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandHelp(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Lets you look up specific commands, or get a link to a list of all commands."; }
|
public String HelpText() { return LocStrings.Stub("HelpInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -25,11 +24,7 @@ public class CommandHelp extends Command
|
|||||||
|
|
||||||
if(help == null)
|
if(help == null)
|
||||||
{
|
{
|
||||||
help = "You can get help with a specific command by typing `!help command`!"
|
help = LocStrings.Stub("HelpDisplay");
|
||||||
+ "\nYou can also look at <https://www.rinsnowmew.com/bot/info/#commands>"
|
|
||||||
+ "\nGeneral Commands: `boop, roll, choose, help, info, vote, "
|
|
||||||
+ "results, showpoll, wolfram, cplus, java,"
|
|
||||||
+ "beans, role, bet, yeet`";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import core.Stats;
|
import core.Stats;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
@@ -25,7 +26,7 @@ public class CommandHelpBuilder extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Emit help for all commands as formatted HTML"; }
|
public String HelpText() { return LocStrings.Stub("HelpBuilderInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
import dataStructures.KittyRating;
|
import dataStructures.KittyRating;
|
||||||
@@ -14,13 +15,11 @@ public class CommandInfo extends Command
|
|||||||
public CommandInfo(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandInfo(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Provides author info and a link to Kitty's website"; }
|
public String HelpText() { return LocStrings.Stub("InfoInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
String info = "I'm made by `Rin#8904` and `Reverie Wisp#3703`!\n"
|
res.Call(LocStrings.Stub("InfoResponse"));
|
||||||
+ "You can find more info about me along with a Patreon link to support us and GitHub link for filing bugs https://www.rinsnowmew.com/bot/" ;
|
|
||||||
res.Call(info);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
import offline.Ref;
|
import offline.Ref;
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ public class CommandInvite extends Command
|
|||||||
public CommandInvite(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandInvite(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Provies a direct invite link for KittyBot"; }
|
public String HelpText() { return LocStrings.Stub("InviteInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
import network.NetworkJDoodle;
|
import network.NetworkJDoodle;
|
||||||
|
|
||||||
@@ -11,11 +12,17 @@ public class CommandJDoodle extends Command
|
|||||||
public CommandJDoodle(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandJDoodle(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Will compile any java code you put in! Supports Java 1.8"; }
|
public String HelpText() { return LocStrings.Stub("JDoodleInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
|
if(input.args.trim().length() < 1)
|
||||||
|
{
|
||||||
|
res.Call(LocStrings.Stub("JDoodleError"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
res.Call(compiler.compileJava(input.args));
|
res.Call(compiler.compileJava(input.args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package commands;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
import dataStructures.KittyRating;
|
import dataStructures.KittyRating;
|
||||||
@@ -22,7 +23,7 @@ public class CommandMap extends Command
|
|||||||
public CommandMap(KittyRole roleLevel, KittyRating contentRating) { super(roleLevel, contentRating); }
|
public CommandMap(KittyRole roleLevel, KittyRating contentRating) { super(roleLevel, contentRating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Generates a map! You can pass additional information if you want with the flags `-s<seed> -w<width> -h<height>`. If one of the fields isn't provided, its default will be used. Note that adjusting the width and height impacts the map outcomes.\n\nDefault seed: Random,\nDefault Width: 35(max "+ MaxWidth + "),\nDefault Height: 25(max " + MaxHeight + ")"; }
|
public String HelpText() { return String.format(LocStrings.Stub("MapInfo"), "" + MaxWidth, "" + MaxHeight); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -59,7 +60,7 @@ public class CommandMap extends Command
|
|||||||
}
|
}
|
||||||
catch(NumberFormatException e)
|
catch(NumberFormatException e)
|
||||||
{
|
{
|
||||||
res.Call("Invalid arguments provided!");
|
res.Call(LocStrings.Stub("MapInvalid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,8 +76,10 @@ public class CommandMap extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Response header creation
|
// Response header creation
|
||||||
header += "Using mapgen v0.1\n";
|
header += LocStrings.Stub("MapVersion") + "\n";
|
||||||
header += "Seed: `" + seed + "`, Width: `"+ width +"`, Height: `"+ height + "`\n";
|
header += LocStrings.Stub("MapSeed") + ": `" + seed + "`, ";
|
||||||
|
header += LocStrings.Stub("MapWidth") + "`"+ width +"`, ";
|
||||||
|
header += LocStrings.Stub("MapHeight") + ": `"+ height + "`\n";
|
||||||
|
|
||||||
// Response body creation
|
// Response body creation
|
||||||
body += "```\n";
|
body += "```\n";
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.io.IOException;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
import dataStructures.KittyRating;
|
import dataStructures.KittyRating;
|
||||||
@@ -22,7 +23,7 @@ public class CommandPerish extends Command
|
|||||||
public CommandPerish(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandPerish(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned"; };
|
public String HelpText() { return LocStrings.Stub("PerishInfo"); };
|
||||||
|
|
||||||
private static Long num = 0l;
|
private static Long num = 0l;
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ public class CommandPing extends Command
|
|||||||
public CommandPing(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandPing(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Will respond with Pong!"; }
|
public String HelpText() { return LocStrings.Stub("PingInfo"); }
|
||||||
|
|
||||||
// Called when the command is run!
|
// Called when the command is run!
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
res.Call("Pong!");
|
res.Call(LocStrings.Stub("PingResponse"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class CommandPollManage extends Command
|
|||||||
public CommandPollManage(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandPollManage(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "'start' will start a new poll with the query of the line you put after, 'choice' will add a choice to the poll, 'stop' will end the poll"; }
|
public String HelpText() { return LocStrings.Stub("PollManageInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class CommandPollResults extends Command
|
|||||||
public CommandPollResults(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandPollResults(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Will show current results of a poll and percentages of votes per choice"; }
|
public String HelpText() { return LocStrings.Stub("PollResultsInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -24,10 +24,11 @@ public class CommandPollResults extends Command
|
|||||||
totalVotes += votes.get(i).votes;
|
totalVotes += votes.get(i).votes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
results += "The poll was " + guild.poll + "\n";
|
||||||
|
|
||||||
for(int i = 0; i < votes.size(); i++)
|
for(int i = 0; i < votes.size(); i++)
|
||||||
{
|
{
|
||||||
|
results += String.format(LocStrings.Stub("PollResultsResponse"), votes.get(i).votes, votes.get(i).choice, (int)(((double)votes.get(i).votes) / ((double)totalVotes) * 100));
|
||||||
results += votes.get(i).votes + " people voted for `" + votes.get(i).choice + "` with `" + (int)(((double)votes.get(i).votes) / ((double)totalVotes) * 100) + "%`!\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Call(results);
|
res.Call(results);
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ public class CommandPollShow extends Command
|
|||||||
public CommandPollShow(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandPollShow(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Will show the current poll running"; }
|
public String HelpText() { return LocStrings.Stub("PollShowInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
if(!guild.polling)
|
if(!guild.polling)
|
||||||
{
|
{
|
||||||
res.Call("There is no poll running!");
|
res.Call(LocStrings.Stub("PollShowNoPoll"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String poll = "The current poll is `" + guild.poll + "`\n";
|
String poll = String.format(LocStrings.Stub("PollShowPoll"), guild.poll);
|
||||||
poll += "And the choices are:\n";
|
poll += LocStrings.Stub("PollShowChoices");
|
||||||
for(int i = 0; i < guild.choices.size(); i++)
|
for(int i = 0; i < guild.choices.size(); i++)
|
||||||
{
|
{
|
||||||
poll += (i+1) + ": `" + guild.choices.get(i).choice + "`\n";
|
poll += (i+1) + ": `" + guild.choices.get(i).choice + "`\n";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public class CommandPollVote extends Command
|
|||||||
public CommandPollVote(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandPollVote(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Vote in a poll with the choice number, won't work if no poll is running, you can't change your vote once you have cast it! Be careful!"; }
|
public String HelpText() { return LocStrings.Stub("PollVoteInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -17,7 +17,7 @@ public class CommandPollVote extends Command
|
|||||||
{
|
{
|
||||||
if(guild.hasVoted.contains(user.uniqueID))
|
if(guild.hasVoted.contains(user.uniqueID))
|
||||||
{
|
{
|
||||||
res.Call("You already voted");
|
res.Call(LocStrings.Stub("PollVoteAlreadyVoted"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
@@ -25,21 +25,23 @@ public class CommandPollVote extends Command
|
|||||||
int voteNum = Integer.parseInt(input.args)-1;
|
int voteNum = Integer.parseInt(input.args)-1;
|
||||||
if(voteNum >= guild.choices.size() || voteNum < 0)
|
if(voteNum >= guild.choices.size() || voteNum < 0)
|
||||||
{
|
{
|
||||||
res.Call(voteNum + " That's not a vaild vote!");
|
res.Call(String.format(LocStrings.Stub("PollVoteNotValidVote"), voteNum));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KittyPoll polled = guild.choices.get(voteNum);
|
KittyPoll polled = guild.choices.get(voteNum);
|
||||||
polled.votes++;
|
polled.votes++;
|
||||||
guild.hasVoted.add(user.uniqueID);
|
guild.hasVoted.add(user.uniqueID);
|
||||||
res.Call("You successfully voted for `" + polled.choice + "`!");
|
res.Call(LocStrings.Stub("PollVoteSuccess") + " `" + polled.choice + "`!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e)
|
catch (NumberFormatException e)
|
||||||
{
|
{
|
||||||
res.Call("That's not a vaild number!");
|
res.Call(LocStrings.Stub("PollVoteNotValidNumber"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.Call("There is no poll running!");
|
|
||||||
|
res.Call(LocStrings.Stub("PollVoteNoPoll"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import core.RPManager;
|
import core.RPManager;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
|
|
||||||
@@ -13,24 +14,30 @@ public class CommandRPEnd extends Command
|
|||||||
public CommandRPEnd (KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandRPEnd (KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Ends RP in channel"; }
|
public String HelpText() { return LocStrings.Stub("RPEndInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
File sending = null;
|
File sending = null;
|
||||||
try {
|
|
||||||
|
try
|
||||||
|
{
|
||||||
sending = RPManager.instance.endRP(channel, user);
|
sending = RPManager.instance.endRP(channel, user);
|
||||||
} catch (FileNotFoundException | UnsupportedEncodingException e)
|
}
|
||||||
|
catch (FileNotFoundException | UnsupportedEncodingException e)
|
||||||
{
|
{
|
||||||
System.out.println("I don't know how you got here");
|
System.out.println("I don't know how you got here");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sending != null)
|
if(sending != null)
|
||||||
{
|
{
|
||||||
res.CallFile(sending, "txt");
|
res.CallFile(sending, "txt");
|
||||||
res.Call("Here's your file!");
|
res.Call(LocStrings.Stub("RPEndFileOut"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res.Call("You can't end this RP!");
|
{
|
||||||
|
res.Call(LocStrings.Stub("RPEndError"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import core.rpg.RPGFramework;
|
import core.rpg.RPGFramework;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
@@ -22,7 +23,7 @@ public class CommandRPG extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Admin+ command only right now - experimental text RPG! Format is !rpg <rpg command>"; };
|
public String HelpText() { return LocStrings.Stub("RPGInfo"); };
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -30,7 +31,9 @@ public class CommandRPG extends Command
|
|||||||
{
|
{
|
||||||
if(input.args == null || input.args.length() == 0)
|
if(input.args == null || input.args.length() == 0)
|
||||||
{
|
{
|
||||||
res.Call(HelpText());
|
String output = HelpText();
|
||||||
|
System.out.println("Out: |" + output + "|");
|
||||||
|
res.Call(output);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +45,7 @@ public class CommandRPG extends Command
|
|||||||
|
|
||||||
if(result == null)
|
if(result == null)
|
||||||
{
|
{
|
||||||
res.Call("Invalid RPG Command!");
|
res.Call(LocStrings.Stub("RPGInvalid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package commands;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import core.RPManager;
|
import core.RPManager;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ public class CommandRPStart extends Command
|
|||||||
public CommandRPStart (KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandRPStart (KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Starts an rp, add people to it by mentioning them!"; }
|
public String HelpText() { return LocStrings.Stub("RPStartInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
import dataStructures.KittyRating;
|
import dataStructures.KittyRating;
|
||||||
@@ -14,7 +15,7 @@ public class CommandRating extends Command
|
|||||||
public CommandRating(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandRating(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "'0' is fully sfw (Derpi and e621 searches are disabled), '1' is filtered (kitty auto appends a sfw tag on any searches), '2' is nsfw (any search will go through). Some other words are supported for setting filter as well."; }
|
public String HelpText() { return LocStrings.Stub("RatingInfo"); }
|
||||||
|
|
||||||
// Called when the command is run!
|
// Called when the command is run!
|
||||||
@Override
|
@Override
|
||||||
@@ -54,11 +55,11 @@ public class CommandRating extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(newRating != null)
|
if(newRating != null)
|
||||||
res.Call("Kittybot content set to " + newRating);
|
res.Call(LocStrings.Stub("RatingChanged") + " " + newRating);
|
||||||
else
|
else
|
||||||
res.Call("Invalid content rating `" + input.args + "`");
|
res.Call(LocStrings.Stub("RatingInvalid") + " `" + input.args + "`");
|
||||||
|
|
||||||
if(newRating.equals("Filtered"))
|
if(newRating.equals("Filtered"))
|
||||||
res.Call("Warning: NSFW may slip through, images are only based on tags on their respective sites!");
|
res.Call(LocStrings.Stub("RatingWarning"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
|
|
||||||
public class CommandRole extends Command
|
public class CommandRole extends Command
|
||||||
@@ -8,20 +9,20 @@ public class CommandRole extends Command
|
|||||||
public CommandRole (KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandRole (KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Will show the current role you have, Admins can change others roles with input of 'role x @y' with x being blacklist, general, mod, or admin. Blacklist will not allow the user to interact with kitty anymore, general mod and admin will give the user access to those commands."; }
|
public String HelpText() { return LocStrings.Stub("RoleInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
if(input.args.isEmpty())
|
if(input.args.isEmpty())
|
||||||
{
|
{
|
||||||
res.Call("Your role is " + user.GetRole().name() + "!");
|
res.Call(LocStrings.Stub("RoleStandardResponse") + " " + user.GetRole().name() + "!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(user.GetRole().getValue() < KittyRole.Admin.getValue())
|
if(user.GetRole().getValue() < KittyRole.Admin.getValue())
|
||||||
{
|
{
|
||||||
res.Call("You aren't allowed to do that! You must have the KittyRole '" + KittyRole.Admin.toString() + "' or higher!");
|
res.Call(String.format(LocStrings.Stub("RoleError"), KittyRole.Admin.toString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ public class CommandRole extends Command
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
res.Call("Please enter `general`, `mod`, or `admin`!");
|
res.Call(LocStrings.Stub("RoleNeededRole"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String users = "";
|
String users = "";
|
||||||
@@ -55,6 +56,6 @@ public class CommandRole extends Command
|
|||||||
users += input.mentions[i].name + " ";
|
users += input.mentions[i].name + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Call("Changed " + users + " to role `" + newRole.name() + "`!");
|
res.Call(String.format(LocStrings.Stub("RoleChanged"), users, newRole.name()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class CommandRoll extends Command
|
|||||||
public CommandRoll(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandRoll(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Based on input of xdy where x is number of dice and y is faces kitty will roll that amount of dice, display the individual rolls and total"; }
|
public String HelpText() { return LocStrings.Stub("RollInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
@@ -27,7 +27,7 @@ public class CommandRoll extends Command
|
|||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
res.Call("Didn't work ;3;");
|
res.Call(LocStrings.Stub("RollError"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package commands;
|
|||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
import core.DatabaseManager;
|
import core.DatabaseManager;
|
||||||
|
import core.LocStrings;
|
||||||
import core.Stats;
|
import core.Stats;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
@@ -10,6 +11,8 @@ import dataStructures.KittyRole;
|
|||||||
import dataStructures.KittyUser;
|
import dataStructures.KittyUser;
|
||||||
import dataStructures.Response;
|
import dataStructures.Response;
|
||||||
import dataStructures.UserInput;
|
import dataStructures.UserInput;
|
||||||
|
import utils.GlobalLog;
|
||||||
|
import utils.LogFilter;
|
||||||
|
|
||||||
// NOTE(wisp): This is a sort of special command.
|
// NOTE(wisp): This is a sort of special command.
|
||||||
public class CommandShutdown extends Command
|
public class CommandShutdown extends Command
|
||||||
@@ -17,7 +20,7 @@ public class CommandShutdown extends Command
|
|||||||
public CommandShutdown(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandShutdown(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown."; }
|
public String HelpText() { return LocStrings.Stub("ShutdownInfo"); }
|
||||||
|
|
||||||
// Called when the command is run!
|
// Called when the command is run!
|
||||||
@Override
|
@Override
|
||||||
@@ -40,13 +43,14 @@ public class CommandShutdown extends Command
|
|||||||
|
|
||||||
if(isSafe)
|
if(isSafe)
|
||||||
{
|
{
|
||||||
DatabaseManager.instance.Upkeep(); // Force upkeep, this works so long as on main thread.
|
// Force upkeep, this works so long as upkeep is on the main thread.
|
||||||
res.CallImmediate("Forced shutdown, database synced before abandoning threads.");
|
DatabaseManager.instance.Upkeep();
|
||||||
|
GlobalLog.Error(LogFilter.Command, "Forced shutdown, database synced before abandoning threads.");
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res.CallImmediate("Forced immediate shutdown, threads abandoned without sync.");
|
GlobalLog.Error(LogFilter.Command, "Forced immediate shutdown, threads abandoned without sync.");
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.io.IOException;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
import utils.ImageUtils;
|
import utils.ImageUtils;
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ public class CommandStark extends Command
|
|||||||
public CommandStark(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandStark(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Snaps your icon or the icon of a friend you mentioned"; };
|
public String HelpText() { return LocStrings.Stub("StarkInfo"); };
|
||||||
|
|
||||||
private static Long num = 0l;
|
private static Long num = 0l;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import core.CommandManager.ThreadData;
|
import core.CommandManager.ThreadData;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
@@ -16,7 +17,7 @@ public class CommandStats extends Command
|
|||||||
public CommandStats(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandStats(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Displays the actively running KittyBot application information"; }
|
public String HelpText() { return LocStrings.Stub("StatsInfo"); }
|
||||||
|
|
||||||
// Called when the command is run!
|
// Called when the command is run!
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package commands;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
|
import dataStructures.KittyChannel;
|
||||||
|
import dataStructures.KittyGuild;
|
||||||
|
import dataStructures.KittyRating;
|
||||||
|
import dataStructures.KittyRole;
|
||||||
|
import dataStructures.KittyUser;
|
||||||
|
import dataStructures.Response;
|
||||||
|
import dataStructures.UserInput;
|
||||||
|
import utils.ImageOverlayBuilder;
|
||||||
|
import utils.ImageUtils;
|
||||||
|
|
||||||
|
public class CommandTeey extends Command
|
||||||
|
{
|
||||||
|
// Required constructor
|
||||||
|
public CommandTeey(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
|
private static Long num = 0l;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String HelpText() { return LocStrings.Stub("TeeyInfo"); }
|
||||||
|
|
||||||
|
// Called when the command is run!
|
||||||
|
@Override
|
||||||
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
|
{
|
||||||
|
String name = null;
|
||||||
|
File teeyFile = null;
|
||||||
|
File teeyeeFile = null;
|
||||||
|
|
||||||
|
synchronized(num)
|
||||||
|
{
|
||||||
|
name = "teey_" + num + ".gif";
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KittyUser person = null;
|
||||||
|
|
||||||
|
if(input.mentions == null)
|
||||||
|
person = user;
|
||||||
|
else
|
||||||
|
person = input.mentions[0];
|
||||||
|
|
||||||
|
String yeeteeFilename = ImageUtils.DownloadFromURL(person.avatarID, ".png");
|
||||||
|
if(yeeteeFilename == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
teeyeeFile = new File(yeeteeFilename);
|
||||||
|
ImageOverlayBuilder builder = new ImageOverlayBuilder("assets/teey/frames/", "teey ", 24, 18);
|
||||||
|
builder.Overlay(ImageIO.read(teeyeeFile), name);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
teeyFile = new File (name);
|
||||||
|
res.CallFile(teeyFile, "gif");
|
||||||
|
|
||||||
|
// Thread cleanup...
|
||||||
|
ImageUtils.BlockingFileDelete(teeyFile);
|
||||||
|
ImageUtils.BlockingFileDelete(teeyeeFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
import network.NetworkTwitter;
|
import network.NetworkTwitter;
|
||||||
|
|
||||||
@@ -10,15 +11,16 @@ public class CommandTweet extends Command
|
|||||||
public CommandTweet(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandTweet(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "With an input of x,y,z where x y and z are all choices, kitty will choose one"; }
|
public String HelpText() { return LocStrings.Stub("TweetInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
|
//TODO: Figure out how to pass pictures correctly
|
||||||
try {
|
try {
|
||||||
res.Call(tweet.tweet(input.args));
|
res.Call(tweet.tweet(input.args));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
res.Call("FUCKED UP HARD");
|
res.Call(LocStrings.Stub("TweetError"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package commands;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.*;
|
import dataStructures.*;
|
||||||
import network.*;
|
import network.*;
|
||||||
import utils.ImageUtils;
|
import utils.ImageUtils;
|
||||||
@@ -14,13 +15,13 @@ public class CommandWolfram extends Command
|
|||||||
public CommandWolfram(KittyRole level, KittyRating rating) { super(level, rating);}
|
public CommandWolfram(KittyRole level, KittyRating rating) { super(level, rating);}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Will query wolframalpha with your question and give a full image output of the answer"; }
|
public String HelpText() { return LocStrings.Stub("WolframInfo"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||||
{
|
{
|
||||||
if(input.args == null || input.args.trim().length() == 0)
|
if(input.args == null || input.args.trim().length() == 0)
|
||||||
res.Call("You need to provide some arguments!");
|
res.Call(LocStrings.Stub("WolframNoArgs"));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -30,7 +31,7 @@ public class CommandWolfram extends Command
|
|||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
res.Call("Something went wrong!");
|
res.Call(LocStrings.Stub("WolframError"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,10 @@
|
|||||||
package commands;
|
package commands;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.awt.image.DataBufferByte;
|
|
||||||
import java.awt.image.RenderedImage;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import javax.imageio.IIOImage;
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.ImageWriteParam;
|
|
||||||
import javax.imageio.ImageWriter;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
|
||||||
import javax.imageio.stream.FileImageOutputStream;
|
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
|
||||||
|
|
||||||
import core.Command;
|
import core.Command;
|
||||||
|
import core.LocStrings;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
import dataStructures.KittyRating;
|
import dataStructures.KittyRating;
|
||||||
@@ -27,18 +12,18 @@ import dataStructures.KittyRole;
|
|||||||
import dataStructures.KittyUser;
|
import dataStructures.KittyUser;
|
||||||
import dataStructures.Response;
|
import dataStructures.Response;
|
||||||
import dataStructures.UserInput;
|
import dataStructures.UserInput;
|
||||||
|
import utils.ImageOverlayBuilder;
|
||||||
import utils.ImageUtils;
|
import utils.ImageUtils;
|
||||||
|
|
||||||
public class CommandYeet extends Command
|
public class CommandYeet extends Command
|
||||||
{
|
{
|
||||||
|
|
||||||
// Required constructor
|
// Required constructor
|
||||||
public CommandYeet(KittyRole level, KittyRating rating) { super(level, rating); }
|
public CommandYeet(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||||
|
|
||||||
private static Long num = 0l;
|
private static Long num = 0l;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String HelpText() { return "Yeet yourself or yeet a friend with @!"; }
|
public String HelpText() { return LocStrings.Stub("YeetInfo"); }
|
||||||
|
|
||||||
// Called when the command is run!
|
// Called when the command is run!
|
||||||
@Override
|
@Override
|
||||||
@@ -59,20 +44,17 @@ public class CommandYeet extends Command
|
|||||||
KittyUser person = null;
|
KittyUser person = null;
|
||||||
|
|
||||||
if(input.mentions == null)
|
if(input.mentions == null)
|
||||||
{
|
|
||||||
person = user;
|
person = user;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
person = input.mentions[0];
|
person = input.mentions[0];
|
||||||
}
|
|
||||||
|
|
||||||
String yeeteeFilename = ImageUtils.DownloadFromURL(person.avatarID, ".png");
|
String yeeteeFilename = ImageUtils.DownloadFromURL(person.avatarID, ".png");
|
||||||
if(yeeteeFilename == null)
|
if(yeeteeFilename == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
yeeteeFile = new File(yeeteeFilename);
|
yeeteeFile = new File(yeeteeFilename);
|
||||||
YEET(ImageIO.read(yeeteeFile), name);
|
ImageOverlayBuilder builder = new ImageOverlayBuilder("assets/yeet/frames/", "yeet ", 24, 18);
|
||||||
|
builder.Overlay(ImageIO.read(yeeteeFile), name);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -86,251 +68,4 @@ public class CommandYeet extends Command
|
|||||||
ImageUtils.BlockingFileDelete(yeetFile);
|
ImageUtils.BlockingFileDelete(yeetFile);
|
||||||
ImageUtils.BlockingFileDelete(yeeteeFile);
|
ImageUtils.BlockingFileDelete(yeeteeFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lets get some trash established for the yeet
|
|
||||||
public static final boolean VERBOSE = false;
|
|
||||||
public static final int NONE = -1;
|
|
||||||
public static final int PIXEL_BYTE_LENGTH = 4; // 32-bit PNG, RGBA
|
|
||||||
public static final String YEET_BASE_PATH = "assets/yeet/frames/";
|
|
||||||
public static final int YEET_BASE_SIZE = 24;
|
|
||||||
public static final int YEET_FPS = 18;
|
|
||||||
|
|
||||||
// Some small logging functions... cause we're professionals...
|
|
||||||
public static void Verbose(String str) { if(VERBOSE) Log("[Verbose] " + str); }
|
|
||||||
public static void Log(String str) { System.out.println("[Log] " + str); }
|
|
||||||
public static void Warn(String str) { System.out.println("[Warn] " + str); }
|
|
||||||
public static void Error(String str) { System.out.println("[Error] " + str); }
|
|
||||||
|
|
||||||
// Performs the Y E E T (image overlay per frame specified, catches IO errors as a note.)
|
|
||||||
public static void YEET(BufferedImage overlay, String outpath)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
long start = Calendar.getInstance().getTimeInMillis();
|
|
||||||
|
|
||||||
ProcessYeet(overlay, outpath);
|
|
||||||
|
|
||||||
long end = Calendar.getInstance().getTimeInMillis();
|
|
||||||
Log("Took " + (end - start) + "ms");
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Processing the image frames to construct a gif. Relies on (0,255,0) pixel for image center specification.
|
|
||||||
public static void ProcessYeet(BufferedImage overlay, String outfileName) throws IOException
|
|
||||||
{
|
|
||||||
BufferedImage[] frames = new BufferedImage[YEET_BASE_SIZE];
|
|
||||||
|
|
||||||
for(int i = 0; i < YEET_BASE_SIZE; ++i)
|
|
||||||
{
|
|
||||||
BufferedImage out = CombineImages(YEET_BASE_PATH + "yeet " + i + ".png", overlay);
|
|
||||||
|
|
||||||
if(out != null)
|
|
||||||
frames[i] = out;
|
|
||||||
else
|
|
||||||
Error("There was an issue with frame " + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
Verbose("Processed " + YEET_BASE_SIZE + " frames, writing...");
|
|
||||||
ImageOutputStream output = new FileImageOutputStream(new File(outfileName));
|
|
||||||
GifSequenceWriter writer = new GifSequenceWriter(output, frames[0].getType(), YEET_FPS, true);
|
|
||||||
|
|
||||||
for(int i = 0; i < YEET_BASE_SIZE; ++i)
|
|
||||||
writer.writeToSequence(frames[i]);
|
|
||||||
|
|
||||||
writer.close();
|
|
||||||
output.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Performs an overlay at a pixel location. We're making some assumptions here, mostly that there is going
|
|
||||||
// to be an RGBA-32-bit encoded PNG image read in for our parsing purposes. We then look for a 0, 255, 0
|
|
||||||
// green pixel on the base frame to apply the overlay buffer to, centered.
|
|
||||||
public static BufferedImage CombineImages(String pathBase, BufferedImage overlay) throws IOException
|
|
||||||
{
|
|
||||||
// Acquire images
|
|
||||||
BufferedImage imageBase = null;
|
|
||||||
BufferedImage imageOverlay = overlay;
|
|
||||||
|
|
||||||
imageBase = ImageIO.read(new File(pathBase));
|
|
||||||
|
|
||||||
// Grab data we know won't change. As a side note, I discovered you can get specific pixels a bit
|
|
||||||
// differently later, but it was too late, I wrote the pixel specific code already.
|
|
||||||
final byte[] pixelsBase = ((DataBufferByte) imageBase.getRaster().getDataBuffer()).getData();
|
|
||||||
final int baseWidth = imageBase.getWidth();
|
|
||||||
final int overlayWidth = imageOverlay.getWidth();
|
|
||||||
final int baseHeight = imageBase.getHeight();
|
|
||||||
final int overlayHeight = imageOverlay.getHeight();
|
|
||||||
|
|
||||||
// Warn about odd sizing when applicable
|
|
||||||
if(overlayHeight > baseHeight || overlayWidth > baseWidth)
|
|
||||||
Warn("Size mismatch, overlay is larger. May function, but not supported.");
|
|
||||||
|
|
||||||
// Skim base picture for solid green pixel to use as target center
|
|
||||||
int targetX = NONE;
|
|
||||||
int targetY = NONE;
|
|
||||||
for(int i = 0; i < pixelsBase.length; i += PIXEL_BYTE_LENGTH)
|
|
||||||
{
|
|
||||||
final int x = ((i / PIXEL_BYTE_LENGTH) % baseWidth);
|
|
||||||
final int y = ((i / PIXEL_BYTE_LENGTH) / baseWidth);
|
|
||||||
|
|
||||||
final int r = (pixelsBase[i]);
|
|
||||||
final int g = (pixelsBase[i + 1]);
|
|
||||||
final int b = (pixelsBase[i + 2]);
|
|
||||||
//final int a = (pixelsBase[i + 3]);
|
|
||||||
|
|
||||||
// Max contrast in 32-bit PNG for green is no red no blue, max green (ratio), max alpha (implied 0 here)
|
|
||||||
if(r == -1 && g == 0 && b == -1)
|
|
||||||
{
|
|
||||||
//Log("Found target pixel at x: " + x + " y: " + y);
|
|
||||||
targetX = x;
|
|
||||||
targetY = y;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip overlay if we have no target location
|
|
||||||
if(targetX == NONE || targetY == NONE)
|
|
||||||
{
|
|
||||||
Verbose("No overlay required for this frame.");
|
|
||||||
return imageBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-create a new byte array and establish overlay bounds
|
|
||||||
final int left = targetX - overlayWidth / 2;
|
|
||||||
final int right = targetX + overlayWidth / 2;
|
|
||||||
final int top = targetY - overlayHeight / 2;
|
|
||||||
final int bottom = targetY + overlayHeight / 2;
|
|
||||||
|
|
||||||
// Apply overlay when appropriate
|
|
||||||
for(int i = 0; i < pixelsBase.length; i += PIXEL_BYTE_LENGTH)
|
|
||||||
{
|
|
||||||
final int x = ((i / PIXEL_BYTE_LENGTH) % baseWidth);
|
|
||||||
final int y = ((i / PIXEL_BYTE_LENGTH) / baseWidth);
|
|
||||||
|
|
||||||
// If we're within the bounds of where the overlay picture should go...
|
|
||||||
if(x > left && x < right && y > top && y < bottom)
|
|
||||||
{
|
|
||||||
final int overlayX = x - left;
|
|
||||||
final int overlayY = y - top;
|
|
||||||
|
|
||||||
// Skip out of bounds pixels
|
|
||||||
if(overlayX < 0 || overlayY < 0 || overlayX >= baseWidth || overlayY >= baseHeight)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Re-write bytes as overlay
|
|
||||||
imageBase.setRGB(x, y, imageOverlay.getRGB(overlayX, overlayY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give the frame back
|
|
||||||
return imageBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// GifSequenceWriter.java
|
|
||||||
//
|
|
||||||
// Created by Elliot Kroo on 2009-04-25,
|
|
||||||
// (Small modifications by wisp in 2018)
|
|
||||||
//
|
|
||||||
// This work is licensed under the Creative Commons Attribution 3.0 Unported License.
|
|
||||||
// To view a copy of this license visit http://creativecommons.org/licenses/by/3.0/
|
|
||||||
// NOTE(wisp): This is Elliot's original license
|
|
||||||
public static class GifSequenceWriter
|
|
||||||
{
|
|
||||||
protected ImageWriter gifWriter;
|
|
||||||
protected ImageWriteParam imageWriteParam;
|
|
||||||
protected IIOMetadata imageMetaData;
|
|
||||||
|
|
||||||
// NOTE: This is limited to things that divide into 1000 cleanly as multiples of 10.
|
|
||||||
public GifSequenceWriter(ImageOutputStream outputStream, int imageType, int framesPerSecond, boolean isLooping) throws IIOException, IOException
|
|
||||||
{
|
|
||||||
gifWriter = getWriter();
|
|
||||||
imageWriteParam = gifWriter.getDefaultWriteParam();
|
|
||||||
ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imageType);
|
|
||||||
|
|
||||||
imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);
|
|
||||||
|
|
||||||
String metaFormatName = imageMetaData.getNativeMetadataFormatName();
|
|
||||||
|
|
||||||
IIOMetadataNode root = (IIOMetadataNode) imageMetaData.getAsTree(metaFormatName);
|
|
||||||
IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
|
|
||||||
graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
|
|
||||||
graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
|
|
||||||
graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
|
|
||||||
graphicsControlExtensionNode.setAttribute("delayTime", "" + (int) ((1000.0 / framesPerSecond) / 10.0)); // THis line isn't super well honored
|
|
||||||
graphicsControlExtensionNode.setAttribute("transparentColorIndex","0");
|
|
||||||
|
|
||||||
IIOMetadataNode appEntensionsNode = getNode( root, "ApplicationExtensions");
|
|
||||||
IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
|
|
||||||
child.setAttribute("applicationID", "NETSCAPE");
|
|
||||||
child.setAttribute("authenticationCode", "2.0");
|
|
||||||
|
|
||||||
int loopValue = isLooping ? 0 : 1;
|
|
||||||
child.setUserObject(new byte[]{ 0x1, (byte) (loopValue & 0xFF), (byte) ((loopValue >> 8) & 0xFF)});
|
|
||||||
appEntensionsNode.appendChild(child);
|
|
||||||
|
|
||||||
imageMetaData.setFromTree(metaFormatName, root);
|
|
||||||
|
|
||||||
gifWriter.setOutput(outputStream);
|
|
||||||
gifWriter.prepareWriteSequence(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeToSequence(RenderedImage img) throws IOException
|
|
||||||
{
|
|
||||||
gifWriter.writeToSequence(new IIOImage(img, null, imageMetaData), imageWriteParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close this GifSequenceWriter object. This does not close the underlying
|
|
||||||
* stream, just finishes off the GIF.
|
|
||||||
*/
|
|
||||||
public void close() throws IOException
|
|
||||||
{
|
|
||||||
gifWriter.endWriteSequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the first available GIF ImageWriter using
|
|
||||||
* ImageIO.getImageWritersBySuffix("gif").
|
|
||||||
*
|
|
||||||
* @return a GIF ImageWriter object
|
|
||||||
* @throws IIOException if no GIF image writers are returned
|
|
||||||
*/
|
|
||||||
private static ImageWriter getWriter() throws IIOException
|
|
||||||
{
|
|
||||||
Iterator<ImageWriter> iter = ImageIO.getImageWritersBySuffix("gif");
|
|
||||||
|
|
||||||
if(!iter.hasNext())
|
|
||||||
throw new IIOException("No GIF Image Writers Exist");
|
|
||||||
else
|
|
||||||
return iter.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an existing child node, or creates and returns a new child node (if
|
|
||||||
* the requested node does not exist).
|
|
||||||
*
|
|
||||||
* @param rootNode the <tt>IIOMetadataNode</tt> to search for the child node.
|
|
||||||
* @param nodeName the name of the child node.
|
|
||||||
*
|
|
||||||
* @return the child node, if found or a new node created with the given name.
|
|
||||||
*/
|
|
||||||
private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName)
|
|
||||||
{
|
|
||||||
int nodeCount = rootNode.getLength();
|
|
||||||
for (int i = 0; i < nodeCount; i++)
|
|
||||||
{
|
|
||||||
if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) == 0)
|
|
||||||
return((IIOMetadataNode) rootNode.item(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
IIOMetadataNode node = new IIOMetadataNode(nodeName);
|
|
||||||
rootNode.appendChild(node);
|
|
||||||
|
|
||||||
return(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package core;
|
package core;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
import dataStructures.KittyRating;
|
import dataStructures.KittyRating;
|
||||||
@@ -42,7 +41,7 @@ public abstract class Command
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO(wisp, rin): ADD CHANNEL CHECK HERE
|
//TODO: ADD CHANNEL CHECK HERE
|
||||||
|
|
||||||
if(user.GetRole().getValue() >= roleLevel.getValue())
|
if(user.GetRole().getValue() >= roleLevel.getValue())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
package core;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import utils.FileUtils;
|
||||||
|
import utils.GlobalLog;
|
||||||
|
import utils.LogFilter;
|
||||||
|
|
||||||
|
// While some of the patterns in this file are similar to the localization files,
|
||||||
|
// commands that are being looked up will behave slightly differently so trimming
|
||||||
|
// rules for this file are different than the localization ones - this is more
|
||||||
|
// aggresive with whitespace removal.
|
||||||
|
public class CommandEnabler
|
||||||
|
{
|
||||||
|
// Config/const variables
|
||||||
|
public static final String filename = "commands.config";
|
||||||
|
public static final String pairSplit = "=";
|
||||||
|
public static final char pairSeparator = '\n';
|
||||||
|
public static final String enabled = "1";
|
||||||
|
public static final String disabled = "0";
|
||||||
|
public static final boolean defaultEnabledState = true;
|
||||||
|
|
||||||
|
// Local variables
|
||||||
|
private HashMap<String, Boolean> enabledMap; // Quick lookup
|
||||||
|
private ArrayList<String> keyList; // Tracking ordering for later
|
||||||
|
|
||||||
|
public CommandEnabler()
|
||||||
|
{
|
||||||
|
GlobalLog.Log(LogFilter.Core, "Initializing " + this.getClass().getSimpleName());
|
||||||
|
enabledMap = new HashMap<>();
|
||||||
|
keyList = new ArrayList<>();
|
||||||
|
|
||||||
|
ReadIn();
|
||||||
|
GetTrackedCommands();
|
||||||
|
WriteOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads in the config file and parses it, keeping tabs on the order it read things
|
||||||
|
private void ReadIn()
|
||||||
|
{
|
||||||
|
File f = new File(filename);
|
||||||
|
if(f.isFile() && f.canRead())
|
||||||
|
{
|
||||||
|
String content = FileUtils.ReadContent(f).trim();
|
||||||
|
String[] lines = content.split("" + pairSeparator);
|
||||||
|
|
||||||
|
for(int i = 0; i < lines.length; ++i)
|
||||||
|
{
|
||||||
|
String[] pair = lines[i].split(pairSplit);
|
||||||
|
|
||||||
|
if(pair.length < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String key = pair[0].trim();
|
||||||
|
String value = pair[1].trim().toLowerCase();
|
||||||
|
|
||||||
|
keyList.add(key);
|
||||||
|
|
||||||
|
if(value.equalsIgnoreCase(enabled))
|
||||||
|
enabledMap.putIfAbsent(key, true);
|
||||||
|
else
|
||||||
|
enabledMap.putIfAbsent(key, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up the already scraped values from the localizer and store them if they
|
||||||
|
// don't already exist in the lookup. Defaults to defaultEnabledState.
|
||||||
|
private void GetTrackedCommands()
|
||||||
|
{
|
||||||
|
ArrayList<String> unloc = LocCommands.GetUnlocalizedCommands();
|
||||||
|
|
||||||
|
for(int i = 0; i < unloc.size(); ++i)
|
||||||
|
{
|
||||||
|
String command = unloc.get(i);
|
||||||
|
if(enabledMap.putIfAbsent(command, defaultEnabledState) == null)
|
||||||
|
{
|
||||||
|
GlobalLog.Log(LogFilter.Strings, "Identified new toggleable raw command: " + command);
|
||||||
|
keyList.add(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out enabled/disabled file info.
|
||||||
|
private void WriteOut()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String outString = "";
|
||||||
|
for(int i = 0; i < keyList.size(); ++i)
|
||||||
|
{
|
||||||
|
String key = keyList.get(i);
|
||||||
|
String value = enabled;
|
||||||
|
|
||||||
|
if(enabledMap.get(key) == false)
|
||||||
|
value = disabled;
|
||||||
|
|
||||||
|
outString += key + pairSplit + value + pairSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
|
||||||
|
writer.write(outString);
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
GlobalLog.Error(LogFilter.Core, "Command enabler issue writing file! " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Looks up a key to see if it's enabled or not
|
||||||
|
public boolean IsEnabled(String key)
|
||||||
|
{
|
||||||
|
if(enabledMap.containsKey(key))
|
||||||
|
return enabledMap.get(key);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import java.util.Map.Entry;
|
|||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
import dataStructures.KittyUser;
|
import dataStructures.KittyUser;
|
||||||
|
import dataStructures.Pair;
|
||||||
import dataStructures.Response;
|
import dataStructures.Response;
|
||||||
import dataStructures.UserInput;
|
import dataStructures.UserInput;
|
||||||
import utils.GlobalLog;
|
import utils.GlobalLog;
|
||||||
@@ -16,22 +17,40 @@ public class CommandManager
|
|||||||
// Variables
|
// Variables
|
||||||
private HashMap<String, Command> commands;
|
private HashMap<String, Command> commands;
|
||||||
private ArrayList<CommandThread> threadAccumulator;
|
private ArrayList<CommandThread> threadAccumulator;
|
||||||
|
private CommandEnabler commandEnabler;
|
||||||
private long invokeCount;
|
private long invokeCount;
|
||||||
|
|
||||||
|
|
||||||
// Default Constructor
|
// Default Constructor
|
||||||
public CommandManager()
|
public CommandManager(CommandEnabler commandEnabler)
|
||||||
{
|
{
|
||||||
commands = new HashMap<String, Command>();
|
this.commands = new HashMap<String, Command>();
|
||||||
threadAccumulator = new ArrayList<CommandThread>();
|
this.threadAccumulator = new ArrayList<CommandThread>();
|
||||||
invokeCount = 0;
|
this.invokeCount = 0;
|
||||||
|
this.commandEnabler = commandEnabler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows the command manager to keep track of a command.
|
// Allows the command manager to keep track of a command. Takes a pair (the un-localized and localzied commands)
|
||||||
public void Register(String key, Command command)
|
// and the command associated with the localized commands.
|
||||||
{
|
public void Register(Pair<String, String> pair, Command command)
|
||||||
if(key == null)
|
{
|
||||||
return;
|
if(pair == null || pair.Second == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If we haven't already split a multisplit command (or even assessed that),
|
||||||
|
// then verify if we even need to register the commands at all. If it's
|
||||||
|
// not enabled, don't register it.
|
||||||
|
if(pair.First != null && !commandEnabler.IsEnabled(pair.First))
|
||||||
|
return;
|
||||||
|
|
||||||
|
String key = pair.Second;
|
||||||
|
|
||||||
|
if(key.contains(","))
|
||||||
|
{
|
||||||
|
|
||||||
|
String[] keys = key.split(",");
|
||||||
|
Register(keys, command);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
key = key.toLowerCase();
|
key = key.toLowerCase();
|
||||||
command.registeredNames.add(key);
|
command.registeredNames.add(key);
|
||||||
@@ -51,7 +70,7 @@ public class CommandManager
|
|||||||
public void Register(String[] keys, Command command)
|
public void Register(String[] keys, Command command)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < keys.length; ++i)
|
for(int i = 0; i < keys.length; ++i)
|
||||||
Register(keys[i], command);
|
Register(new Pair<String, String>(null, keys[i].trim()), command);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calls the command but on a whole new thread!
|
// Calls the command but on a whole new thread!
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
package core;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import dataStructures.TaggedPairStore;
|
||||||
|
import utils.FileUtils;
|
||||||
|
import utils.GlobalLog;
|
||||||
|
import utils.LogFilter;
|
||||||
|
|
||||||
|
// A quick-and-dirty localization tool that scrapes the project for calls to itself, then
|
||||||
|
// generates/updates a file externally with all the stub values as keys that are localized.
|
||||||
|
public abstract class LocBase
|
||||||
|
{
|
||||||
|
// Pre-defined values
|
||||||
|
public static final String KittySourceDirectory = "./src";
|
||||||
|
|
||||||
|
// Filename
|
||||||
|
public final String filename; // Example: "localization.config";
|
||||||
|
public final String functionName; // Example: "Localizer.Stub";
|
||||||
|
|
||||||
|
// Local translation storage
|
||||||
|
protected TaggedPairStore stringStore;
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
private void Log(String str) { GlobalLog.Log(LogFilter.Strings, str); }
|
||||||
|
private void Warn(String str) { GlobalLog.Warn(LogFilter.Strings, str); }
|
||||||
|
private void Error(String str) { GlobalLog.Error(LogFilter.Strings, str); }
|
||||||
|
|
||||||
|
// Ok... so this is an array because if it's not an array, the parser will parse the string
|
||||||
|
public LocBase(String filename, String functionName)
|
||||||
|
{
|
||||||
|
this.filename = filename;
|
||||||
|
this.functionName = functionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Structure used for holding a pair of strings and any other info we need
|
||||||
|
// about localized information that is being looked up.
|
||||||
|
private class LocInfo
|
||||||
|
{
|
||||||
|
public String file;
|
||||||
|
public String phrase;
|
||||||
|
|
||||||
|
public LocInfo(String f, String p)
|
||||||
|
{
|
||||||
|
this.file = f;
|
||||||
|
this.phrase = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do processing on each path in the scraped directory here, assuming it's .java
|
||||||
|
public void StripForContents(Path path, ArrayList<LocInfo> strings)
|
||||||
|
{
|
||||||
|
String filename = path.getFileName().toString();
|
||||||
|
if(filename.contains(".java"))
|
||||||
|
{
|
||||||
|
String contents = FileUtils.ReadContent(path);
|
||||||
|
String[] split = contents.split(functionName);
|
||||||
|
|
||||||
|
// Identify all localizer function calls
|
||||||
|
for(int i = 1; i < split.length; ++i)
|
||||||
|
{
|
||||||
|
int loc = split[i].indexOf(")");
|
||||||
|
String noWhitespace = split[i].replaceAll("\\s+","");
|
||||||
|
|
||||||
|
if(loc != -1)
|
||||||
|
{
|
||||||
|
if(noWhitespace.charAt(noWhitespace.indexOf(")") - 1) == '"' && split[i].charAt(loc - 2) != '\\')
|
||||||
|
{
|
||||||
|
// At this point, we find the first ), then verify there's a ") behind it, and that
|
||||||
|
// the " is not an escaped character.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String toLocalize = split[i].substring(2, loc - 1);
|
||||||
|
|
||||||
|
strings.add(new LocInfo(filename.substring(0, filename.lastIndexOf('.')), toLocalize));
|
||||||
|
|
||||||
|
Log("Found lookup call in " + path + ": " + toLocalize);
|
||||||
|
}
|
||||||
|
catch(IndexOutOfBoundsException e)
|
||||||
|
{
|
||||||
|
Warn("Found phrase but couldn't parse in file " + path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing for now, but in the future will return a parsed and localized version of
|
||||||
|
// the string in question if one can be found. If the localized string is empty,
|
||||||
|
// returns a the key instead which is the default phrase.
|
||||||
|
public String GetKey(String input)
|
||||||
|
{
|
||||||
|
if(stringStore == null)
|
||||||
|
return input;
|
||||||
|
|
||||||
|
String value = stringStore.GetKey(input);
|
||||||
|
if(value == null || value.trim().length() < 1)
|
||||||
|
return input;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads a file to string, adapted from https://stackoverflow.com/a/326440/5383198
|
||||||
|
private String ReadFileAsString(String path, Charset encoding)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] encoded = Files.readAllBytes(Paths.get(path));
|
||||||
|
return new String(encoded, encoding);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Warn("No file found to read from!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update localization from the disk on file. Creates the file if it doesn't exist.
|
||||||
|
// This file is internally formatted as an ini file.
|
||||||
|
public void UpdateLocFromDisk()
|
||||||
|
{
|
||||||
|
Log("Attempting to read localization file: " + filename);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String fileContents = ReadFileAsString(filename, Charset.defaultCharset());
|
||||||
|
|
||||||
|
if(fileContents == null)
|
||||||
|
{
|
||||||
|
File file = new File(filename);
|
||||||
|
file.createNewFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
stringStore = new TaggedPairStore(fileContents);
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
Error("IO exception during localization file read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rewrites out at the specified filename with existing stubs.
|
||||||
|
// This preserves existing localized phrases.
|
||||||
|
public void SaveLocToDisk()
|
||||||
|
{
|
||||||
|
Log("Attempting to write updated localization file");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PrintWriter pw = new PrintWriter(filename);
|
||||||
|
pw.println(stringStore.toString());
|
||||||
|
pw.close();
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
Error("IO exception during localization file write");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryStripSpecified(Path path, ArrayList<LocInfo> toFill)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StripForContents(path, toFill);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Error("issue with file: " + path.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scrape the project and generate all the possible localizeable phrases.
|
||||||
|
// This stubs out phrases to be localized.
|
||||||
|
public void ScrapeAll()
|
||||||
|
{
|
||||||
|
ArrayList<LocInfo> localizeList = new ArrayList<LocInfo>();
|
||||||
|
FileUtils.AcquireAllFiles(KittySourceDirectory).forEach((path) -> TryStripSpecified(path, localizeList));
|
||||||
|
|
||||||
|
for(LocInfo toStub : localizeList)
|
||||||
|
stringStore.AddKeyValue(toStub.file, toStub.phrase, toStub.phrase);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package core;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import utils.GlobalLog;
|
||||||
|
import utils.LogFilter;
|
||||||
|
import dataStructures.Pair;
|
||||||
|
|
||||||
|
// Performs the same localization for the strings associated with command names as
|
||||||
|
// is performed with general strings in the application
|
||||||
|
public class LocCommands extends LocBase
|
||||||
|
{
|
||||||
|
public static final String fileName = "locCommands.config";
|
||||||
|
public static final String function = "LocCommands.Stub";
|
||||||
|
|
||||||
|
private static LocCommands instance;
|
||||||
|
|
||||||
|
public LocCommands()
|
||||||
|
{
|
||||||
|
super(fileName, function);
|
||||||
|
|
||||||
|
GlobalLog.Log(LogFilter.Core, "Initializing " + this.getClass().getSimpleName());
|
||||||
|
|
||||||
|
if(instance == null)
|
||||||
|
{
|
||||||
|
instance = this;
|
||||||
|
|
||||||
|
UpdateLocFromDisk();
|
||||||
|
ScrapeAll();
|
||||||
|
SaveLocToDisk();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GlobalLog.Error(LogFilter.Core, "You can't have two of the following: " + this.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a pair, the raw key and the stub key
|
||||||
|
public static Pair<String, String> Stub(String toStub)
|
||||||
|
{
|
||||||
|
return new Pair<String, String>(toStub, instance.GetKey(toStub));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets all of the un-translated defaults in the commands list.
|
||||||
|
public static ArrayList<String> GetUnlocalizedCommands()
|
||||||
|
{
|
||||||
|
ArrayList<String> raw = new ArrayList<>();
|
||||||
|
instance.stringStore.ForEach((pair) -> raw.add((String)((Pair<?, ?>)pair).First ));
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package core;
|
||||||
|
|
||||||
|
import utils.GlobalLog;
|
||||||
|
import utils.LogFilter;
|
||||||
|
|
||||||
|
// A quick-and-dirty localization tool that scrapes the project for calls to itself, then
|
||||||
|
// generates/updates a file externally (phrases.config) with all the stub values as keys that
|
||||||
|
// can then be localized.
|
||||||
|
public class LocStrings extends LocBase
|
||||||
|
{
|
||||||
|
public static final String fileName = "locStrings.config";
|
||||||
|
public static final String function = "LocStrings.Stub";
|
||||||
|
|
||||||
|
private static LocStrings instance;
|
||||||
|
|
||||||
|
public LocStrings()
|
||||||
|
{
|
||||||
|
super(fileName, function);
|
||||||
|
|
||||||
|
GlobalLog.Log(LogFilter.Core, "Initializing " + this.getClass().getSimpleName());
|
||||||
|
|
||||||
|
if(instance == null)
|
||||||
|
{
|
||||||
|
instance = this;
|
||||||
|
|
||||||
|
UpdateLocFromDisk();
|
||||||
|
ScrapeAll();
|
||||||
|
SaveLocToDisk();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GlobalLog.Error(LogFilter.Core, "You can't have two of the following: " + this.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String Stub(String toStub)
|
||||||
|
{
|
||||||
|
return instance.GetKey(toStub);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
package core;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import org.ini4j.InvalidFileFormatException;
|
|
||||||
import org.ini4j.Profile.Section;
|
|
||||||
import org.ini4j.Wini;
|
|
||||||
|
|
||||||
import utils.FileUtils;
|
|
||||||
import utils.GlobalLog;
|
|
||||||
import utils.LogFilter;
|
|
||||||
|
|
||||||
// A quick-and-dirty localization tool that scrapes the project for calls to itself, then
|
|
||||||
// generates/updates a file externally (phrases.config) with all the stub values as keys that
|
|
||||||
// can then be localized.
|
|
||||||
public class Localizer
|
|
||||||
{
|
|
||||||
// Filename
|
|
||||||
public final static String filename = "localization.config";
|
|
||||||
public final static String functionName = "Localizer.Stub";
|
|
||||||
|
|
||||||
// Local translation
|
|
||||||
private static HashMap<String, LocInfo> translated = new HashMap<String, LocInfo>();
|
|
||||||
|
|
||||||
// Logging
|
|
||||||
private static void Log(String str) { GlobalLog.Log(LogFilter.Strings, str); }
|
|
||||||
private static void Warn(String str) { GlobalLog.Warn(LogFilter.Strings, str); }
|
|
||||||
private static void Error(String str) { GlobalLog.Error(LogFilter.Strings, str); }
|
|
||||||
|
|
||||||
// Structure used for holding a pair of strings and any other info we need
|
|
||||||
// about localized information that is being looked up.
|
|
||||||
private static class LocInfo
|
|
||||||
{
|
|
||||||
public String file;
|
|
||||||
public String phrase;
|
|
||||||
|
|
||||||
public LocInfo(String f, String p)
|
|
||||||
{
|
|
||||||
this.file = f;
|
|
||||||
this.phrase = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do processing on each path in the scraped directory here, assuming it's .java
|
|
||||||
public static void StripForContents(Path path, ArrayList<LocInfo> strings)
|
|
||||||
{
|
|
||||||
String filename = path.getFileName().toString();
|
|
||||||
if(filename.contains(".java"))
|
|
||||||
{
|
|
||||||
String contents = FileUtils.ReadContent(path);
|
|
||||||
String[] split = contents.split(functionName);
|
|
||||||
|
|
||||||
// Identify all localizer function calls
|
|
||||||
for(int i = 1; i < split.length; ++i)
|
|
||||||
{
|
|
||||||
int loc = split[i].indexOf(")");
|
|
||||||
|
|
||||||
if(loc != -1)
|
|
||||||
{
|
|
||||||
if(split[i].charAt(loc - 1) == '"' && split[i].charAt(loc - 2) != '\\')
|
|
||||||
{
|
|
||||||
// At this point, we find the first ), then verify there's a ") behind it, and that
|
|
||||||
// the " is not an escaped character.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String toLocalize = split[i].substring(2, loc - 1);
|
|
||||||
|
|
||||||
strings.add(new LocInfo(filename.substring(0, filename.lastIndexOf('.')), toLocalize));
|
|
||||||
|
|
||||||
Log("Found stubbed phrase in " + path + " : " + toLocalize);
|
|
||||||
}
|
|
||||||
catch(IndexOutOfBoundsException e)
|
|
||||||
{
|
|
||||||
Warn("Found phrase but couldn't parse in file " + path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing for now, but in the future will return a parsed and localized version of
|
|
||||||
// the string in question if one can be found.
|
|
||||||
public static String Stub(String input)
|
|
||||||
{
|
|
||||||
if(translated.containsKey(input))
|
|
||||||
{
|
|
||||||
String value = translated.get(input).phrase;
|
|
||||||
if(value.trim().length() > 0)
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update localization from the disk on file. Creates the file if it doesn't exist.
|
|
||||||
// This file is internally formatted as an ini file.
|
|
||||||
public static void UpdateLocFromDisk()
|
|
||||||
{
|
|
||||||
Log("Attempting to read localization file");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File file = new File(filename);
|
|
||||||
file.createNewFile();
|
|
||||||
|
|
||||||
Wini ini = new Wini(file);
|
|
||||||
|
|
||||||
for(String str : ini.keySet())
|
|
||||||
{
|
|
||||||
// Store everything in all .ini sections
|
|
||||||
Section sec = ini.get(str);
|
|
||||||
for(String s : sec.keySet())
|
|
||||||
{
|
|
||||||
if(!translated.containsKey(s))
|
|
||||||
translated.put(s, new LocInfo(sec.getName(), sec.get(s, String.class)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(InvalidFileFormatException e)
|
|
||||||
{
|
|
||||||
Error("File issue with format during localization file read");
|
|
||||||
}
|
|
||||||
catch(IOException e)
|
|
||||||
{
|
|
||||||
Error("IO exception during localization file read");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rewrites out at the specified filename with existing stubs.
|
|
||||||
// This preserves existing localized phrases.
|
|
||||||
public static void SaveLocToDisk()
|
|
||||||
{
|
|
||||||
Log("Attempting to write updated localization file");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
PrintWriter pw = new PrintWriter(filename);
|
|
||||||
pw.close();
|
|
||||||
|
|
||||||
File file = new File(filename);
|
|
||||||
file.createNewFile();
|
|
||||||
|
|
||||||
Wini ini = new Wini(file);
|
|
||||||
|
|
||||||
for(String s : translated.keySet())
|
|
||||||
{
|
|
||||||
LocInfo toWrite = translated.get(s);
|
|
||||||
ini.put(toWrite.file, s, toWrite.phrase);
|
|
||||||
}
|
|
||||||
|
|
||||||
ini.store();
|
|
||||||
}
|
|
||||||
catch(InvalidFileFormatException e)
|
|
||||||
{
|
|
||||||
Error("File issue with format during localization file write");
|
|
||||||
}
|
|
||||||
catch(IOException e)
|
|
||||||
{
|
|
||||||
Error("IO exception during localization file write");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scrape the project and generate all the possible localizeable phrases.
|
|
||||||
// This stubs out phrases to be localized.
|
|
||||||
public static void ScrapeAll()
|
|
||||||
{
|
|
||||||
ArrayList<LocInfo> localizeList = new ArrayList<LocInfo>();
|
|
||||||
FileUtils.AcquireAllFiles(".\\src").forEach((path) -> StripForContents(path, localizeList));
|
|
||||||
|
|
||||||
for(LocInfo toStub : localizeList)
|
|
||||||
{
|
|
||||||
if(!translated.containsKey(toStub.phrase))
|
|
||||||
{
|
|
||||||
translated.put(toStub.phrase, new LocInfo(toStub.file, ""));
|
|
||||||
Log("Found new stubbed phrase '" + toStub.phrase + "' in " + toStub.file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,17 +3,58 @@ package core;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
import commands.*;
|
import commands.CommandAddGuildRole;
|
||||||
import dataStructures.*;
|
import commands.CommandAllowedGuildRole;
|
||||||
|
import commands.CommandBeansShow;
|
||||||
|
import commands.CommandBetBeans;
|
||||||
|
import commands.CommandBlurry;
|
||||||
|
import commands.CommandBoop;
|
||||||
|
import commands.CommandChangeIndicator;
|
||||||
|
import commands.CommandChoose;
|
||||||
|
import commands.CommandColiru;
|
||||||
|
import commands.CommandDoWork;
|
||||||
|
import commands.CommandEightBall;
|
||||||
|
import commands.CommandGiveBeans;
|
||||||
|
import commands.CommandHelp;
|
||||||
|
import commands.CommandHelpBuilder;
|
||||||
|
import commands.CommandInfo;
|
||||||
|
import commands.CommandInvite;
|
||||||
|
import commands.CommandJDoodle;
|
||||||
|
import commands.CommandMap;
|
||||||
|
import commands.CommandPerish;
|
||||||
|
import commands.CommandPing;
|
||||||
|
import commands.CommandPollManage;
|
||||||
|
import commands.CommandPollResults;
|
||||||
|
import commands.CommandPollShow;
|
||||||
|
import commands.CommandPollVote;
|
||||||
|
import commands.CommandRPEnd;
|
||||||
|
import commands.CommandRPG;
|
||||||
|
import commands.CommandRPStart;
|
||||||
|
import commands.CommandRating;
|
||||||
|
import commands.CommandRole;
|
||||||
|
import commands.CommandRoll;
|
||||||
|
import commands.CommandShutdown;
|
||||||
|
import commands.CommandStark;
|
||||||
|
import commands.CommandStats;
|
||||||
|
import commands.CommandTeey;
|
||||||
|
import commands.CommandTweet;
|
||||||
|
import commands.CommandWolfram;
|
||||||
|
import commands.CommandYeet;
|
||||||
|
import dataStructures.KittyChannel;
|
||||||
|
import dataStructures.KittyGuild;
|
||||||
|
import dataStructures.KittyRating;
|
||||||
|
import dataStructures.KittyRole;
|
||||||
|
import dataStructures.KittyUser;
|
||||||
import net.dv8tion.jda.core.entities.Member;
|
import net.dv8tion.jda.core.entities.Member;
|
||||||
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
|
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
|
||||||
|
import utils.AdminControl;
|
||||||
import utils.GlobalLog;
|
import utils.GlobalLog;
|
||||||
import utils.LogFilter;
|
import utils.LogFilter;
|
||||||
|
|
||||||
// NOTE(wisp): Isolated factory to assist with storage and caching if needed.
|
// NOTE(wisp): Isolated factory to assist with storage and caching if needed.
|
||||||
// This also minimizes the number of places JDA interacts with our codebase.
|
// This also minimizes the number of places JDA interacts with our codebase.
|
||||||
// As it stands, if the object name begins with Kitty, it's constructed here.
|
// As it stands, if the object name begins with Kitty, it's constructed here.
|
||||||
// TODO: Make all methods ID based instead of event based
|
// TODO: Make all methods ID based instead of event based
|
||||||
public class ObjectBuilderFactory
|
public class ObjectBuilderFactory
|
||||||
{
|
{
|
||||||
// Key: guild string id, Value: guild information
|
// Key: guild string id, Value: guild information
|
||||||
@@ -34,9 +75,20 @@ public class ObjectBuilderFactory
|
|||||||
// RPManger for tracking RP system
|
// RPManger for tracking RP system
|
||||||
private static RPManager rpManager;
|
private static RPManager rpManager;
|
||||||
|
|
||||||
// Lazy initialization style for
|
// Localization classes - these are singletons, but should be initialized before almost all other
|
||||||
|
// things so their inclusion in the factory is to ensure they're started at the correct time.
|
||||||
|
@SuppressWarnings("unused") private static LocStrings locStrings;
|
||||||
|
@SuppressWarnings("unused") private static LocCommands locCommands;
|
||||||
|
|
||||||
|
// Handles if we can or can't use specific commands, parsing a config file based on loc data to do so.
|
||||||
|
private static CommandEnabler commandEnabler;
|
||||||
|
|
||||||
|
// Lazy initialization multithreaded mutex stuff to prevent explosions.
|
||||||
|
// TODO: Investigate using 'synchronized' instead potentially
|
||||||
private static boolean hasInitialized;
|
private static boolean hasInitialized;
|
||||||
private static Semaphore initMutex = new Semaphore(1);
|
private static Semaphore initMutex = new Semaphore(1);
|
||||||
|
|
||||||
|
// This is it, this is how the lazy init starts!
|
||||||
private static void LazyInit()
|
private static void LazyInit()
|
||||||
{
|
{
|
||||||
if(hasInitialized)
|
if(hasInitialized)
|
||||||
@@ -47,26 +99,31 @@ public class ObjectBuilderFactory
|
|||||||
initMutex.acquire();
|
initMutex.acquire();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Initialization here. This is where we could read from something external.
|
// structure initialization
|
||||||
|
// Construct necessary data structures.
|
||||||
guildCache = new HashMap<String, KittyGuild>();
|
guildCache = new HashMap<String, KittyGuild>();
|
||||||
userCache = new HashMap<String, KittyUser>();
|
userCache = new HashMap<String, KittyUser>();
|
||||||
channelCache = new HashMap<String, KittyChannel>();
|
channelCache = new HashMap<String, KittyChannel>();
|
||||||
database = null;
|
database = null;
|
||||||
stats = null;
|
stats = null;
|
||||||
|
|
||||||
|
// Start by reading from things that are external. Because
|
||||||
|
// we require these things to be resolved before the rest of the application,
|
||||||
|
// we place them here.
|
||||||
|
locStrings = new LocStrings();
|
||||||
|
locCommands = new LocCommands();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
initMutex.release();
|
initMutex.release();
|
||||||
|
hasInitialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(InterruptedException ie)
|
catch(InterruptedException ie)
|
||||||
{
|
{
|
||||||
GlobalLog.Error(LogFilter.Core, "Issue during object builder lazy initialization."
|
GlobalLog.Error(LogFilter.Core, "Issue during object builder lazy initialization."
|
||||||
+ " The factory was not initialized, "
|
+ " The factory was not initialized, and kitty will not be able to continue functionally.");
|
||||||
+ "and kitty will not be able to continue functionally.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasInitialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicitly locks: guildCache
|
// Explicitly locks: guildCache
|
||||||
@@ -79,7 +136,7 @@ public class ObjectBuilderFactory
|
|||||||
// look up the guild.
|
// look up the guild.
|
||||||
String uid = event.getGuild().getId();
|
String uid = event.getGuild().getId();
|
||||||
|
|
||||||
// ince we're lazily initialized, we can synchronize w/ the
|
// once we're lazily initialized, we can synchronize w/ the
|
||||||
// guildCache object now instead of having to use a mutex.
|
// guildCache object now instead of having to use a mutex.
|
||||||
KittyGuild guild = null;
|
KittyGuild guild = null;
|
||||||
synchronized (guildCache)
|
synchronized (guildCache)
|
||||||
@@ -92,7 +149,7 @@ public class ObjectBuilderFactory
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Construct a new guild with defaults
|
// Construct a new guild with defaults
|
||||||
guild = new KittyGuild(uid);
|
guild = new KittyGuild(uid, new AdminControl(event.getGuild()));
|
||||||
DatabaseManager.instance.Register(guild);
|
DatabaseManager.instance.Register(guild);
|
||||||
guildCache.put(uid, guild);
|
guildCache.put(uid, guild);
|
||||||
}
|
}
|
||||||
@@ -276,58 +333,72 @@ public class ObjectBuilderFactory
|
|||||||
user.avatarID = member.getUser().getAvatarUrl();
|
user.avatarID = member.getUser().getAvatarUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default construction of the command manager.
|
// Constructs a CommandEnabler if it doesn't exist, and gets the existing one if it does.
|
||||||
// TODO(wisp): We want to be able to keep all this data
|
public static CommandEnabler ConstructCommandEnabler()
|
||||||
// stored off in a file at some point, so we can reflect it onto the
|
{
|
||||||
// project and build it per-guild. That's for later now tho.
|
LazyInit();
|
||||||
public static CommandManager ConstructCommandManager()
|
|
||||||
|
if(commandEnabler == null)
|
||||||
|
commandEnabler = new CommandEnabler();
|
||||||
|
|
||||||
|
return commandEnabler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default construction of the command manager. In order to remotely resolve command enabling
|
||||||
|
// and disabling, what we do is construct the commands with a localized pair that is checked against
|
||||||
|
// the CommandEnabler object passed in. In theory, we could have multiple CommandManagers, tho we can
|
||||||
|
// only have one CommandEnabler.
|
||||||
|
public static CommandManager ConstructCommandManager(CommandEnabler commandEnabler)
|
||||||
{
|
{
|
||||||
LazyInit();
|
LazyInit();
|
||||||
|
|
||||||
CommandManager manager = new CommandManager();
|
CommandManager manager = new CommandManager(commandEnabler);
|
||||||
|
|
||||||
manager.Register("work", new CommandDoWork(KittyRole.Dev, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("work"), new CommandDoWork(KittyRole.Dev, KittyRating.Safe));
|
||||||
manager.Register("shutdown", new CommandShutdown(KittyRole.Dev, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("shutdown"), new CommandShutdown(KittyRole.Dev, KittyRating.Safe));
|
||||||
manager.Register("stats", new CommandStats(KittyRole.Dev, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("stats"), new CommandStats(KittyRole.Dev, KittyRating.Safe));
|
||||||
manager.Register("invite", new CommandInvite(KittyRole.Dev, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("invite"), new CommandInvite(KittyRole.Dev, KittyRating.Safe));
|
||||||
manager.Register("buildHelp", new CommandHelpBuilder(KittyRole.Dev, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("buildHelp"), new CommandHelpBuilder(KittyRole.Dev, KittyRating.Safe));
|
||||||
manager.Register("tweet", new CommandTweet(KittyRole.Dev, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("tweet"), new CommandTweet(KittyRole.Dev, KittyRating.Safe));
|
||||||
|
|
||||||
manager.Register("rating", new CommandRating(KittyRole.Admin, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("rating"), new CommandRating(KittyRole.Admin, KittyRating.Safe));
|
||||||
manager.Register("indicator", new CommandChangeIndicator(KittyRole.Admin, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("indicator"), new CommandChangeIndicator(KittyRole.Admin, KittyRating.Safe));
|
||||||
|
manager.Register(LocCommands.Stub("allowedguildrole"), new CommandAllowedGuildRole(KittyRole.Admin, KittyRating.Safe));
|
||||||
|
|
||||||
manager.Register("poll", new CommandPollManage(KittyRole.Mod, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("poll"), new CommandPollManage(KittyRole.Mod, KittyRating.Safe));
|
||||||
manager.Register("givebeans", new CommandGiveBeans(KittyRole.Mod, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("givebeans"), new CommandGiveBeans(KittyRole.Mod, KittyRating.Safe));
|
||||||
manager.Register("rpg", new CommandRPG(KittyRole.Mod, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("rpg"), new CommandRPG(KittyRole.Mod, KittyRating.Safe));
|
||||||
|
|
||||||
manager.Register(new String[]{"perish", "thenperish"}, new CommandPerish(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("addguildrole"), new CommandAddGuildRole(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("yeet", new CommandYeet(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("teey"), new CommandTeey(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("ping", new CommandPing(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("perish, thenperish"), new CommandPerish(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("boop", new CommandBoop(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("yeet"), new CommandYeet(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("roll", new CommandRoll(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("ping"), new CommandPing(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("choose", new CommandChoose(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("boop"), new CommandBoop(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("help", new CommandHelp(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("roll"), new CommandRoll(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register(new String[] {"info", "about"}, new CommandInfo(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("choose"), new CommandChoose(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("vote", new CommandPollVote(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("help"), new CommandHelp(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("results", new CommandPollResults(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("info, about"), new CommandInfo(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("showpoll", new CommandPollShow(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("vote"), new CommandPollVote(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("wolfram", new CommandWolfram(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("results"), new CommandPollResults(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register(new String[] {"c++", "g++", "cplus",}, new CommandColiru(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("showpoll"), new CommandPollShow(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register(new String[] {"java", "jdoodle" }, new CommandJDoodle(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("wolfram"), new CommandWolfram(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("beans", new CommandBeansShow(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("c++, g++, cplus, cpp"), new CommandColiru(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("role", new CommandRole(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("java, jdoodle"), new CommandJDoodle(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("bet", new CommandBetBeans(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("beans"), new CommandBeansShow(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("map", new CommandMap(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("role"), new CommandRole(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("rpstart", new CommandRPStart(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("bet"), new CommandBetBeans(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("rpend", new CommandRPEnd(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("map"), new CommandMap(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register(new String[] {"tony", "stark", "dontfeelgood", "dontfeelsogood"}, new CommandStark(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("rpstart"), new CommandRPStart(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register("blur", new CommandBlurry(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("rpend"), new CommandRPEnd(KittyRole.General, KittyRating.Safe));
|
||||||
manager.Register(new String [] {"eightball", "8ball"}, new CommandEightBall(KittyRole.General, KittyRating.Safe));
|
manager.Register(LocCommands.Stub("tony, stark, dontfeelgood, dontfeelsogood"), new CommandStark(KittyRole.General, KittyRating.Safe));
|
||||||
|
manager.Register(LocCommands.Stub("blur"), new CommandBlurry(KittyRole.General, KittyRating.Safe));
|
||||||
|
manager.Register(LocCommands.Stub("eightball, 8ball"), new CommandEightBall(KittyRole.General, KittyRating.Safe));
|
||||||
|
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(wisp): Default database manager construction. It can be constructed
|
// Default database manager construction. It can be constructed
|
||||||
// in different ways, and so we construct it outside of the constructor for
|
// in different ways, and so we construct it outside of the constructor for
|
||||||
// the factory since it doesn't have to be present / can be elsewhere.
|
// the factory since it doesn't have to be present / can be elsewhere.
|
||||||
// Effectively we cache the database here.
|
// Effectively we cache the database here.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package dataStructures;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import core.DatabaseTrackedObject;
|
import core.DatabaseTrackedObject;
|
||||||
|
import utils.AdminControl;
|
||||||
|
|
||||||
// Context for a given guild for kittybot. Primarily designed to hold guild-specific settings.
|
// Context for a given guild for kittybot. Primarily designed to hold guild-specific settings.
|
||||||
public class KittyGuild extends DatabaseTrackedObject
|
public class KittyGuild extends DatabaseTrackedObject
|
||||||
@@ -12,17 +13,19 @@ public class KittyGuild extends DatabaseTrackedObject
|
|||||||
public boolean polling;
|
public boolean polling;
|
||||||
public String poll;
|
public String poll;
|
||||||
public ArrayList<String> hasVoted = new ArrayList<String>();
|
public ArrayList<String> hasVoted = new ArrayList<String>();
|
||||||
|
public ArrayList<String> allowedRole = new ArrayList<String>();
|
||||||
public ArrayList <KittyPoll> choices = new ArrayList<KittyPoll>();
|
public ArrayList <KittyPoll> choices = new ArrayList<KittyPoll>();
|
||||||
|
public AdminControl control;
|
||||||
|
|
||||||
private String commandIndicator;
|
private String commandIndicator;
|
||||||
|
|
||||||
// Default content for a guild
|
// Default content for a guild
|
||||||
public KittyGuild(String uniqueID)
|
public KittyGuild(String uniqueID, AdminControl adminControl)
|
||||||
{
|
{
|
||||||
super(uniqueID);
|
super(uniqueID);
|
||||||
|
control = adminControl;
|
||||||
this.uniqueID = uniqueID;
|
this.uniqueID = uniqueID;
|
||||||
this.contentRating = KittyRating.Safe;
|
this.contentRating = KittyRating.Safe;
|
||||||
this.polling = false;
|
this.polling = false;
|
||||||
SetCommandIndicator("!");
|
SetCommandIndicator("!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package dataStructures;
|
||||||
|
|
||||||
|
// A generic class designed to hold two types, as a first and second variable.
|
||||||
|
public class Pair<T1, T2>
|
||||||
|
{
|
||||||
|
public T1 First;
|
||||||
|
public T2 Second;
|
||||||
|
|
||||||
|
public Pair(T1 first, T2 second)
|
||||||
|
{
|
||||||
|
this.First = first;
|
||||||
|
this.Second = second;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
package dataStructures;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
// This is a class designed to parse ini inspired key-value pairs that are sectioned off.
|
||||||
|
// The difference here is that this is more permissive than an ini file, and only accepts
|
||||||
|
// a single split character, not the traditional set an ini does. All of the following are valid:
|
||||||
|
//
|
||||||
|
// [ExampleSection]
|
||||||
|
// Key=Value
|
||||||
|
// Valid Ridiculous Key&\n\t_.:;foo = \tValid Ridiculous Value*&%$()^.[]{}@
|
||||||
|
// EmptyValue=
|
||||||
|
//
|
||||||
|
// Note that the sections are NOT designed to allow for duplicate keys across them.
|
||||||
|
// This is a restriction of the structure, but can be changed later potentially.
|
||||||
|
// The only value not allowed in a key or value is the KeyValueSplit.
|
||||||
|
public class TaggedPairStore
|
||||||
|
{
|
||||||
|
// Variables
|
||||||
|
public final char SectionStart = '[';
|
||||||
|
public final char SectionEnd = ']';
|
||||||
|
public final char PairLineSeparator = '\n';
|
||||||
|
public final String PairSplit = "=";
|
||||||
|
|
||||||
|
// [Key: SectionName, [Key: KeyString, Value: ValueString]]
|
||||||
|
private HashMap<String, HashMap<String, String>> taggedPairs;
|
||||||
|
|
||||||
|
// [Key: KeyString, Value: ValueString]]
|
||||||
|
private HashMap<String, String> allPairs;
|
||||||
|
|
||||||
|
// String constructor that parses the input string into the object
|
||||||
|
public TaggedPairStore(String input)
|
||||||
|
{
|
||||||
|
taggedPairs = new HashMap<String, HashMap<String, String>>();
|
||||||
|
allPairs = new HashMap<String, String>();
|
||||||
|
Parse(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calls back on each item in the entire structure. Provides section, then a pair of the keyString and valueString.
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
public void ForEach(BiConsumer<? super String, Pair<? super String, ? super String>> action)
|
||||||
|
{
|
||||||
|
Iterator it = taggedPairs.entrySet().iterator();
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
Map.Entry pair = (Map.Entry)it.next();
|
||||||
|
Iterator internal = ((HashMap<String, String>)pair.getValue()).entrySet().iterator();
|
||||||
|
|
||||||
|
while(internal.hasNext())
|
||||||
|
{
|
||||||
|
Map.Entry internalPair = (Map.Entry)internal.next();
|
||||||
|
action.accept((String)pair.getKey(), new Pair<String, String>((String)internalPair.getKey(), (String)internalPair.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calls back each item in the structure but does not priv
|
||||||
|
@SuppressWarnings({"rawtypes"})
|
||||||
|
public void ForEach(Consumer<Pair<? super String, ? super String>> action)
|
||||||
|
{
|
||||||
|
Iterator it = allPairs.entrySet().iterator();
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
Map.Entry pair = (Map.Entry)it.next();
|
||||||
|
action.accept(new Pair<String, String>((String)pair.getKey(), (String)pair.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses the internal hashmap as a string then reutrns it, featuring sections.
|
||||||
|
// Iterates over all key/value pairs in the section and print them. Does not print
|
||||||
|
// the value of a given key if it is the same as the key.
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String out = "";
|
||||||
|
|
||||||
|
// Iterates over the sections and
|
||||||
|
Iterator it = taggedPairs.entrySet().iterator();
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
Map.Entry pair = (Map.Entry)it.next();
|
||||||
|
out += ("" + SectionStart + pair.getKey() + SectionEnd + PairLineSeparator);
|
||||||
|
|
||||||
|
Iterator internal = ((HashMap<String, String>)pair.getValue()).entrySet().iterator();
|
||||||
|
while(internal.hasNext())
|
||||||
|
{
|
||||||
|
Map.Entry internalPair = (Map.Entry)internal.next();
|
||||||
|
String key = (String)internalPair.getKey();
|
||||||
|
String value = (String)internalPair.getValue();
|
||||||
|
|
||||||
|
if(key == value)
|
||||||
|
out += (key + PairSplit) + PairLineSeparator;
|
||||||
|
else
|
||||||
|
out += (key + PairSplit + value) + PairLineSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
out += PairLineSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses out the string passed in into the sectionkeyValue HashMap.
|
||||||
|
// Any character used in a split call is escaped just in case on
|
||||||
|
// account of some characters having specific regex meanings.
|
||||||
|
private void Parse(String input)
|
||||||
|
{
|
||||||
|
if(input == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String[] sections = input.split("\\" + SectionStart);
|
||||||
|
|
||||||
|
for(int sec = 0; sec < sections.length; ++sec)
|
||||||
|
{
|
||||||
|
// Gather information about the contents of the section, and the header.
|
||||||
|
String section = sections[sec];
|
||||||
|
if(section.length() < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int pos = section.indexOf(SectionEnd);
|
||||||
|
if(pos == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Parse section name. If it already exists, don't bother making it.
|
||||||
|
String sectionName = section.substring(0, pos);
|
||||||
|
AddSection(sectionName);
|
||||||
|
|
||||||
|
// Parse out the pairs within the section, split them all out.
|
||||||
|
String unparsedPairs = section.substring(pos + 1);
|
||||||
|
String[] pairs = unparsedPairs.split("\\" + PairLineSeparator);
|
||||||
|
|
||||||
|
// Parse out valid key-value pairs, and store them in the specified section.
|
||||||
|
// At this point, we can be guarenteed that sectionName is in the Hashmap.
|
||||||
|
for(int pair = 0; pair < pairs.length; ++pair)
|
||||||
|
{
|
||||||
|
String line = pairs[pair];
|
||||||
|
int splitPos = line.indexOf(PairSplit);
|
||||||
|
if(splitPos < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String key = line.substring(0, splitPos);
|
||||||
|
String value = line.substring(splitPos + PairSplit.length());
|
||||||
|
taggedPairs.get(sectionName).putIfAbsent(key, value);
|
||||||
|
allPairs.putIfAbsent(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dumps out a string array
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void Dump(String[] toPrint)
|
||||||
|
{
|
||||||
|
System.out.println("Length: " + toPrint.length);
|
||||||
|
|
||||||
|
for(int i = 0; i < toPrint.length; ++i)
|
||||||
|
System.out.println(toPrint[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a KeyValue pair to the specified section if it's not already there.
|
||||||
|
// Also creates the section if it's not already present.
|
||||||
|
public void AddKeyValue(String sectionName, String key, String value)
|
||||||
|
{
|
||||||
|
AddSection(sectionName);
|
||||||
|
taggedPairs.get(sectionName).putIfAbsent(key, value);
|
||||||
|
allPairs.putIfAbsent(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a given section to the hashmap if it's not already present
|
||||||
|
public void AddSection(String sectionName)
|
||||||
|
{
|
||||||
|
taggedPairs.putIfAbsent(sectionName, new HashMap<String, String>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a HashMap of Keys to Values for a given section
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public HashMap<String, String> GetSection(String sectionName)
|
||||||
|
{
|
||||||
|
return (HashMap<String, String>) taggedPairs.get(sectionName).clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up a global key
|
||||||
|
public String GetKey(String key)
|
||||||
|
{
|
||||||
|
if(allPairs.containsKey(key))
|
||||||
|
return allPairs.get(key);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package main;
|
package main;
|
||||||
|
|
||||||
import javax.security.auth.login.LoginException;
|
import javax.security.auth.login.LoginException;
|
||||||
|
|
||||||
import core.*;
|
import core.*;
|
||||||
import dataStructures.KittyChannel;
|
import dataStructures.KittyChannel;
|
||||||
import dataStructures.KittyGuild;
|
import dataStructures.KittyGuild;
|
||||||
@@ -14,35 +13,33 @@ import net.dv8tion.jda.core.entities.*;
|
|||||||
import net.dv8tion.jda.core.events.message.guild.*;
|
import net.dv8tion.jda.core.events.message.guild.*;
|
||||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||||
import offline.*;
|
import offline.*;
|
||||||
import core.Localizer;
|
|
||||||
import utils.GlobalLog;
|
import utils.GlobalLog;
|
||||||
import net.dv8tion.jda.core.*;
|
import net.dv8tion.jda.core.*;
|
||||||
|
|
||||||
// NOTE(wisp): http://www.slf4j.org/ - this JDA logging tool has been disabled by specifying NOP implementation.
|
// http://www.slf4j.org/ - this JDA logging tool has been disabled by specifying NOP implementation.
|
||||||
// NOTE(wisp): Application entry point!
|
// This is the application entry point, and bot startup location!
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public class Main extends ListenerAdapter
|
public class Main extends ListenerAdapter
|
||||||
{
|
{
|
||||||
// Variables and stuff
|
// Variables and stuff
|
||||||
private static JDA kitty;
|
private static JDA kitty;
|
||||||
private static CommandManager commandManager;
|
private static CommandManager commandManager;
|
||||||
|
private static CommandEnabler commandEnabler;
|
||||||
private static DatabaseManager databaseManager;
|
private static DatabaseManager databaseManager;
|
||||||
private static Stats stats;
|
private static Stats stats;
|
||||||
private static RPManager rpManager;
|
private static RPManager rpManager;
|
||||||
|
|
||||||
// Main test location
|
// Main test location
|
||||||
public static void main(String[] args) throws InterruptedException, LoginException, Exception
|
public static void main(String[] args) throws InterruptedException, LoginException, Exception
|
||||||
{
|
{
|
||||||
// Facotry startup.
|
// Factory startup. The ordering is intentional.
|
||||||
databaseManager = ObjectBuilderFactory.ConstructDatabaseManager();
|
databaseManager = ObjectBuilderFactory.ConstructDatabaseManager();
|
||||||
commandManager = ObjectBuilderFactory.ConstructCommandManager();
|
commandEnabler = ObjectBuilderFactory.ConstructCommandEnabler();
|
||||||
|
commandManager = ObjectBuilderFactory.ConstructCommandManager(commandEnabler);
|
||||||
rpManager = ObjectBuilderFactory.ConstructRPManager();
|
rpManager = ObjectBuilderFactory.ConstructRPManager();
|
||||||
stats = ObjectBuilderFactory.ConstructStats(commandManager);
|
stats = ObjectBuilderFactory.ConstructStats(commandManager);
|
||||||
|
|
||||||
// Localizer startup - Potentially integrate with the factory.
|
|
||||||
Localizer.UpdateLocFromDisk();
|
|
||||||
Localizer.ScrapeAll();
|
|
||||||
Localizer.SaveLocToDisk();
|
|
||||||
|
|
||||||
// Bot startup
|
// Bot startup
|
||||||
kitty = new JDABuilder(AccountType.BOT).setToken(Ref.TestToken).buildBlocking();
|
kitty = new JDABuilder(AccountType.BOT).setToken(Ref.TestToken).buildBlocking();
|
||||||
kitty.getPresence().setGame(Game.playing("with a new build"));
|
kitty.getPresence().setGame(Game.playing("with a new build"));
|
||||||
@@ -56,8 +53,6 @@ public class Main extends ListenerAdapter
|
|||||||
if(!PreProcessSetup(event))
|
if(!PreProcessSetup(event))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GlobalLog.Log("Parseable message recieved!");
|
|
||||||
|
|
||||||
// Factory objects
|
// Factory objects
|
||||||
KittyUser user = ObjectBuilderFactory.ExtractUser(event);
|
KittyUser user = ObjectBuilderFactory.ExtractUser(event);
|
||||||
KittyGuild guild = ObjectBuilderFactory.ExtractGuild(event);
|
KittyGuild guild = ObjectBuilderFactory.ExtractGuild(event);
|
||||||
@@ -74,7 +69,7 @@ public class Main extends ListenerAdapter
|
|||||||
// Track beans!
|
// Track beans!
|
||||||
user.ChangeBeans(1);
|
user.ChangeBeans(1);
|
||||||
|
|
||||||
//RP logging system
|
// RP logging system
|
||||||
RPManager.instance.addLine(channel, user, input);
|
RPManager.instance.addLine(channel, user, input);
|
||||||
|
|
||||||
// Issue the command
|
// Issue the command
|
||||||
@@ -140,6 +135,7 @@ public class Main extends ListenerAdapter
|
|||||||
{
|
{
|
||||||
databaseManager.Upkeep();
|
databaseManager.Upkeep();
|
||||||
RPManager.Upkeep(kitty);
|
RPManager.Upkeep(kitty);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package network;
|
package network;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import core.*;
|
|
||||||
import dataStructures.GenericImage;
|
import dataStructures.GenericImage;
|
||||||
import offline.*;
|
import offline.*;
|
||||||
import utils.*;
|
import utils.*;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package network;
|
package network;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import core.*;
|
|
||||||
import dataStructures.GenericImage;
|
import dataStructures.GenericImage;
|
||||||
|
import offline.Ref;
|
||||||
import utils.*;
|
import utils.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,7 +25,7 @@ public class NetworkE621
|
|||||||
private static final Gson jsonParser_ = new Gson();
|
private static final Gson jsonParser_ = new Gson();
|
||||||
private static final String API_ROOT = "https://e621.net/post/index.json?";
|
private static final String API_ROOT = "https://e621.net/post/index.json?";
|
||||||
private static int maxSearchResults_ = 10;
|
private static int maxSearchResults_ = 10;
|
||||||
private static String[] blacklist = {"theallseeingeye","scat","diaper","cub"};
|
private static String[] blacklist = Ref.e621Blacklist;
|
||||||
private class E621ResponseObject
|
private class E621ResponseObject
|
||||||
{
|
{
|
||||||
// public varaibles matching the case and the type we want for JSON.
|
// public varaibles matching the case and the type we want for JSON.
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.core.entities.Guild;
|
||||||
|
import net.dv8tion.jda.core.managers.GuildController;
|
||||||
|
|
||||||
|
public class AdminControl
|
||||||
|
{
|
||||||
|
private GuildController guildCon;
|
||||||
|
private Guild guild;
|
||||||
|
|
||||||
|
public AdminControl(Guild guild)
|
||||||
|
{
|
||||||
|
this.guild = guild;
|
||||||
|
guildCon = guild.getController();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addRole(String memberID, String roleName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
guildCon.addRolesToMember(guild.getMemberById(memberID), guild.getRolesByName(roleName, true)).complete();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package utils;
|
package utils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@@ -11,6 +12,7 @@ import java.util.stream.Stream;
|
|||||||
public class FileUtils
|
public class FileUtils
|
||||||
{
|
{
|
||||||
// Reads all lines from a file as a string
|
// Reads all lines from a file as a string
|
||||||
|
public static String ReadContent(File file) { return ReadContent(file.toPath()); }
|
||||||
public static String ReadContent(Path filePath)
|
public static String ReadContent(Path filePath)
|
||||||
{
|
{
|
||||||
StringBuilder contentBuilder = new StringBuilder();
|
StringBuilder contentBuilder = new StringBuilder();
|
||||||
@@ -24,7 +26,7 @@ public class FileUtils
|
|||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
GlobalLog.Error(LogFilter.Util, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return contentBuilder.toString();
|
return contentBuilder.toString();
|
||||||
@@ -35,13 +37,18 @@ public class FileUtils
|
|||||||
{
|
{
|
||||||
ArrayList<Path> items = new ArrayList<Path>();
|
ArrayList<Path> items = new ArrayList<Path>();
|
||||||
|
|
||||||
|
File tmpDir = new File(startingDir);
|
||||||
|
if(!tmpDir.exists())
|
||||||
|
return new ArrayList<Path>();
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Files.find(Paths.get(startingDir), 999, (path, attributes) -> attributes.isRegularFile()).forEach(items::add);
|
Files.find(Paths.get(startingDir), 999, (path, attributes) -> attributes.isRegularFile()).forEach(items::add);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
GlobalLog.Error(LogFilter.Util, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class GlobalLog
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void Log(String msg) { Write(log, LogFilter.Debug, msg); }
|
public static void Log(String msg) { Write(log, LogFilter.Debug, msg); }
|
||||||
public static void Warn(String msg) {Write(warn, LogFilter.Debug, msg); }
|
public static void Warn(String msg) { Write(warn, LogFilter.Debug, msg); }
|
||||||
public static void Error(String msg) { Write(error, LogFilter.Debug, msg); }
|
public static void Error(String msg) { Write(error, LogFilter.Debug, msg); }
|
||||||
public static void Fatal(String msg) throws Exception { Write(fatal, LogFilter.Debug, msg); throw new Exception(msg); }
|
public static void Fatal(String msg) throws Exception { Write(fatal, LogFilter.Debug, msg); throw new Exception(msg); }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,308 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.DataBufferByte;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.IIOImage;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.ImageWriteParam;
|
||||||
|
import javax.imageio.ImageWriter;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
import javax.imageio.stream.FileImageOutputStream;
|
||||||
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
|
|
||||||
|
// A class that overlays an image based on a series of frames that will be converted into a gif.
|
||||||
|
// The class targets a pixel with max Green value and no red or blue that's fully opaque (0, 255, 0)
|
||||||
|
// and then places the center of the overlay image on the specified location. Must be 32-bit PNGs with RGBA format.
|
||||||
|
public class ImageOverlayBuilder
|
||||||
|
{
|
||||||
|
// Lets get some trash established for the yeet
|
||||||
|
public static final boolean VERBOSE = false;
|
||||||
|
public static final int NONE = -1;
|
||||||
|
public static final int PIXEL_BYTE_LENGTH = 4; // 32-bit PNG, RGBA
|
||||||
|
public static final int DEFAULT_FPS = 18;
|
||||||
|
public static final String FRAME_FILE_EXTENSION = ".png";
|
||||||
|
public static final String LOG_HEADER = "[Overlay] ";
|
||||||
|
|
||||||
|
// Logging intermediate functions
|
||||||
|
private static void Verbose(String str) { if(VERBOSE) Log("[Verbose] " + str); }
|
||||||
|
private static void Log(String str) { GlobalLog.Log(LogFilter.Util, LOG_HEADER + str); }
|
||||||
|
private static void Warn(String str) { GlobalLog.Warn(LogFilter.Util, LOG_HEADER + str); }
|
||||||
|
private static void Error(String str) { GlobalLog.Error(LogFilter.Util, LOG_HEADER + str); }
|
||||||
|
|
||||||
|
// Local variables
|
||||||
|
private final String basePath; // The folder location of the files
|
||||||
|
private final String baseName; // This is the consistent part of the filename of each frame, for example "image "
|
||||||
|
private final int frameCount; // The number of frames in the image
|
||||||
|
private final int fps; // This doesn't quite line up, multiples of 10 are as specific as it gets.
|
||||||
|
|
||||||
|
// Required minimal constructor
|
||||||
|
public ImageOverlayBuilder(String basePath, String baseName, int frameCount)
|
||||||
|
{
|
||||||
|
this(basePath, baseName, frameCount, DEFAULT_FPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor with framerate specification
|
||||||
|
public ImageOverlayBuilder(String basePath, String baseName, int frameCount, int fps)
|
||||||
|
{
|
||||||
|
this.basePath = basePath;
|
||||||
|
this.baseName = baseName;
|
||||||
|
this.frameCount = frameCount;
|
||||||
|
this.fps = fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs a per-frame overlay, catches IO errors as a note.)
|
||||||
|
public void Overlay(BufferedImage overlay, String outpath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
long start = Calendar.getInstance().getTimeInMillis();
|
||||||
|
|
||||||
|
ProcessOverlay(overlay, outpath);
|
||||||
|
|
||||||
|
long end = Calendar.getInstance().getTimeInMillis();
|
||||||
|
Log("Took " + (end - start) + "ms");
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processing the image frames to construct a gif. Relies on (0,255,0) pixel for image center specification.
|
||||||
|
private void ProcessOverlay(BufferedImage overlay, String outfileName) throws IOException
|
||||||
|
{
|
||||||
|
BufferedImage[] frames = new BufferedImage[frameCount];
|
||||||
|
|
||||||
|
for(int i = 0; i < frameCount; ++i)
|
||||||
|
{
|
||||||
|
BufferedImage out = CombineImages(basePath + baseName + i + FRAME_FILE_EXTENSION , overlay);
|
||||||
|
|
||||||
|
if(out != null)
|
||||||
|
frames[i] = out;
|
||||||
|
else
|
||||||
|
Error("There was an issue with overlaying frame " + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Verbose("Processed " + frameCount + " frames, writing...");
|
||||||
|
ImageOutputStream output = new FileImageOutputStream(new File(outfileName));
|
||||||
|
GifSequenceWriter writer = new GifSequenceWriter(output, frames[0].getType(), fps, true);
|
||||||
|
|
||||||
|
for(int i = 0; i < frameCount; ++i)
|
||||||
|
writer.writeToSequence(frames[i]);
|
||||||
|
|
||||||
|
writer.close();
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs an overlay at a pixel location. We're making some assumptions here, mostly that there is going
|
||||||
|
// to be an RGBA-32-bit encoded PNG image read in for our parsing purposes. We then look for a 0, 255, 0
|
||||||
|
// green pixel on the base frame to apply the overlay buffer to, centered.
|
||||||
|
private BufferedImage CombineImages(String pathBase, BufferedImage overlay) throws IOException
|
||||||
|
{
|
||||||
|
// Acquire images
|
||||||
|
BufferedImage imageBase = null;
|
||||||
|
BufferedImage imageOverlay = overlay;
|
||||||
|
|
||||||
|
imageBase = ImageIO.read(new File(pathBase));
|
||||||
|
|
||||||
|
// Grab data we know won't change. As a side note, I discovered you can get specific pixels a bit
|
||||||
|
// differently later, but it was too late, I wrote the pixel specific code already.
|
||||||
|
final byte[] pixelsBase = ((DataBufferByte) imageBase.getRaster().getDataBuffer()).getData();
|
||||||
|
final int baseWidth = imageBase.getWidth();
|
||||||
|
final int overlayWidth = imageOverlay.getWidth();
|
||||||
|
final int baseHeight = imageBase.getHeight();
|
||||||
|
final int overlayHeight = imageOverlay.getHeight();
|
||||||
|
|
||||||
|
// Warn about odd sizing when applicable
|
||||||
|
if(overlayHeight > baseHeight || overlayWidth > baseWidth)
|
||||||
|
Warn("Size mismatch, overlay is larger. May function, but not supported.");
|
||||||
|
|
||||||
|
// Skim base picture for solid green pixel to use as target center
|
||||||
|
int targetX = NONE;
|
||||||
|
int targetY = NONE;
|
||||||
|
for(int i = 0; i < pixelsBase.length; i += PIXEL_BYTE_LENGTH)
|
||||||
|
{
|
||||||
|
final int x = ((i / PIXEL_BYTE_LENGTH) % baseWidth);
|
||||||
|
final int y = ((i / PIXEL_BYTE_LENGTH) / baseWidth);
|
||||||
|
|
||||||
|
final int r = (pixelsBase[i]);
|
||||||
|
final int g = (pixelsBase[i + 1]);
|
||||||
|
final int b = (pixelsBase[i + 2]);
|
||||||
|
//final int a = (pixelsBase[i + 3]);
|
||||||
|
|
||||||
|
// Max contrast in 32-bit PNG for green is no red no blue, max green (ratio), max alpha (implied 0 here)
|
||||||
|
if(r == -1 && g == 0 && b == -1)
|
||||||
|
{
|
||||||
|
//Log("Found target pixel at x: " + x + " y: " + y);
|
||||||
|
targetX = x;
|
||||||
|
targetY = y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip overlay if we have no target location
|
||||||
|
if(targetX == NONE || targetY == NONE)
|
||||||
|
{
|
||||||
|
Verbose("No overlay required for this frame.");
|
||||||
|
return imageBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-create a new byte array and establish overlay bounds
|
||||||
|
final int left = targetX - overlayWidth / 2;
|
||||||
|
final int right = targetX + overlayWidth / 2;
|
||||||
|
final int top = targetY - overlayHeight / 2;
|
||||||
|
final int bottom = targetY + overlayHeight / 2;
|
||||||
|
|
||||||
|
// Apply overlay when appropriate
|
||||||
|
for(int i = 0; i < pixelsBase.length; i += PIXEL_BYTE_LENGTH)
|
||||||
|
{
|
||||||
|
final int x = ((i / PIXEL_BYTE_LENGTH) % baseWidth);
|
||||||
|
final int y = ((i / PIXEL_BYTE_LENGTH) / baseWidth);
|
||||||
|
|
||||||
|
// If we're within the bounds of where the overlay picture should go...
|
||||||
|
// ...then get bytes and manually apply alpha overlay.
|
||||||
|
if(x > left && x < right && y > top && y < bottom)
|
||||||
|
{
|
||||||
|
final int overlayX = x - left;
|
||||||
|
final int overlayY = y - top;
|
||||||
|
|
||||||
|
// Skip out of bounds pixels
|
||||||
|
if(overlayX < 0 || overlayY < 0 || overlayX >= baseWidth || overlayY >= baseHeight)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
byte[] overlayBytes = ByteBuffer.allocate(4).putInt(imageOverlay.getRGB(overlayX, overlayY)).array();
|
||||||
|
byte[] baseBytes = ByteBuffer.allocate(4).putInt(imageBase.getRGB(x, y)).array();
|
||||||
|
float overlayT = (overlayBytes[0] & 0xFF) / 255.0f;
|
||||||
|
|
||||||
|
// Java has a restriction where we can't actually manupulate unsigned bytes apparently(?) so
|
||||||
|
// what this does is convert the specific bytes to ints in order to manipuate them, then takes the
|
||||||
|
// byte buffer and parses the far right byte out of the int after manipulating the value.
|
||||||
|
byte[] output = new byte[4];
|
||||||
|
output[0] = (byte)0b11111111;
|
||||||
|
output[1] = ByteBuffer.allocate(4).putInt((int) ((baseBytes[1] & 0xFF) - (overlayT * ((baseBytes[1] & 0xFF) - (overlayBytes[1] & 0xFF))))).array()[3];
|
||||||
|
output[2] = ByteBuffer.allocate(4).putInt((int) ((baseBytes[2] & 0xFF) - (overlayT * ((baseBytes[2] & 0xFF) - (overlayBytes[2] & 0xFF))))).array()[3];
|
||||||
|
output[3] = ByteBuffer.allocate(4).putInt((int) ((baseBytes[3] & 0xFF) - (overlayT * ((baseBytes[3] & 0xFF) - (overlayBytes[3] & 0xFF))))).array()[3];
|
||||||
|
|
||||||
|
// Re-write bytes as overlay
|
||||||
|
imageBase.setRGB(x, y, ByteBuffer.wrap(output).getInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give the frame back
|
||||||
|
return imageBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GifSequenceWriter.java
|
||||||
|
//
|
||||||
|
// Created by Elliot Kroo on 2009-04-25,
|
||||||
|
// (Small modifications by wisp in 2018)
|
||||||
|
//
|
||||||
|
// This work is licensed under the Creative Commons Attribution 3.0 Unported License.
|
||||||
|
// To view a copy of this license visit http://creativecommons.org/licenses/by/3.0/
|
||||||
|
// NOTE: ^ This is Elliot's original license
|
||||||
|
private static class GifSequenceWriter
|
||||||
|
{
|
||||||
|
protected ImageWriter gifWriter;
|
||||||
|
protected ImageWriteParam imageWriteParam;
|
||||||
|
protected IIOMetadata imageMetaData;
|
||||||
|
|
||||||
|
// NOTE: This is limited to things that divide into 1000 cleanly as multiples of 10.
|
||||||
|
public GifSequenceWriter(ImageOutputStream outputStream, int imageType, int framesPerSecond, boolean isLooping) throws IIOException, IOException
|
||||||
|
{
|
||||||
|
gifWriter = getWriter();
|
||||||
|
imageWriteParam = gifWriter.getDefaultWriteParam();
|
||||||
|
ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imageType);
|
||||||
|
|
||||||
|
imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);
|
||||||
|
|
||||||
|
String metaFormatName = imageMetaData.getNativeMetadataFormatName();
|
||||||
|
|
||||||
|
IIOMetadataNode root = (IIOMetadataNode) imageMetaData.getAsTree(metaFormatName);
|
||||||
|
IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
|
||||||
|
graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
|
||||||
|
graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
|
||||||
|
graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
|
||||||
|
graphicsControlExtensionNode.setAttribute("delayTime", "" + (int) ((1000.0 / framesPerSecond) / 10.0)); // THis line isn't super well honored
|
||||||
|
graphicsControlExtensionNode.setAttribute("transparentColorIndex","0");
|
||||||
|
|
||||||
|
IIOMetadataNode appEntensionsNode = getNode( root, "ApplicationExtensions");
|
||||||
|
IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
|
||||||
|
child.setAttribute("applicationID", "NETSCAPE");
|
||||||
|
child.setAttribute("authenticationCode", "2.0");
|
||||||
|
|
||||||
|
int loopValue = isLooping ? 0 : 1;
|
||||||
|
child.setUserObject(new byte[]{ 0x1, (byte) (loopValue & 0xFF), (byte) ((loopValue >> 8) & 0xFF)});
|
||||||
|
appEntensionsNode.appendChild(child);
|
||||||
|
|
||||||
|
imageMetaData.setFromTree(metaFormatName, root);
|
||||||
|
|
||||||
|
gifWriter.setOutput(outputStream);
|
||||||
|
gifWriter.prepareWriteSequence(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeToSequence(RenderedImage img) throws IOException
|
||||||
|
{
|
||||||
|
gifWriter.writeToSequence(new IIOImage(img, null, imageMetaData), imageWriteParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close this GifSequenceWriter object. This does not close the underlying
|
||||||
|
* stream, just finishes off the GIF.
|
||||||
|
*/
|
||||||
|
public void close() throws IOException
|
||||||
|
{
|
||||||
|
gifWriter.endWriteSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first available GIF ImageWriter using
|
||||||
|
* ImageIO.getImageWritersBySuffix("gif").
|
||||||
|
*
|
||||||
|
* @return a GIF ImageWriter object
|
||||||
|
* @throws IIOException if no GIF image writers are returned
|
||||||
|
*/
|
||||||
|
private static ImageWriter getWriter() throws IIOException
|
||||||
|
{
|
||||||
|
Iterator<ImageWriter> iter = ImageIO.getImageWritersBySuffix("gif");
|
||||||
|
|
||||||
|
if(!iter.hasNext())
|
||||||
|
throw new IIOException("No GIF Image Writers Exist");
|
||||||
|
else
|
||||||
|
return iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an existing child node, or creates and returns a new child node (if
|
||||||
|
* the requested node does not exist).
|
||||||
|
*
|
||||||
|
* @param rootNode the <tt>IIOMetadataNode</tt> to search for the child node.
|
||||||
|
* @param nodeName the name of the child node.
|
||||||
|
*
|
||||||
|
* @return the child node, if found or a new node created with the given name.
|
||||||
|
*/
|
||||||
|
private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName)
|
||||||
|
{
|
||||||
|
int nodeCount = rootNode.getLength();
|
||||||
|
for (int i = 0; i < nodeCount; i++)
|
||||||
|
{
|
||||||
|
if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) == 0)
|
||||||
|
return((IIOMetadataNode) rootNode.item(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
IIOMetadataNode node = new IIOMetadataNode(nodeName);
|
||||||
|
rootNode.appendChild(node);
|
||||||
|
|
||||||
|
return(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,8 @@ package utils;
|
|||||||
|
|
||||||
public enum LogFilter
|
public enum LogFilter
|
||||||
{
|
{
|
||||||
Debug(0), Command(1), Core(2), Database(4), Response(8), Network(16), Strings(32); //8, 16, 32... (flags, so we can | together later)
|
// Assign numbers as flags, so we can | ('or') them together as necessary
|
||||||
|
Debug(0), Command(1), Core(2), Util(4), Database(8), Response(16), Network(32), Strings(64);
|
||||||
|
|
||||||
private final int value;
|
private final int value;
|
||||||
private LogFilter(int value)
|
private LogFilter(int value)
|
||||||
|
|||||||