Upgraded to Twitter4J 4.1

This commit is contained in:
Erik C. Thauvin 2022-10-12 20:04:29 -07:00
parent c24fcb8ef5
commit c4cf7b10d5
7 changed files with 70 additions and 60 deletions

View file

@ -76,7 +76,7 @@ dependencies {
implementation 'net.objecthunter:exp4j:0.4.8' implementation 'net.objecthunter:exp4j:0.4.8'
implementation 'org.json:json:20220924' implementation 'org.json:json:20220924'
implementation 'org.jsoup:jsoup:1.15.3' implementation 'org.jsoup:jsoup:1.15.3'
implementation 'org.twitter4j:twitter4j-core:4.0.7' implementation 'org.twitter4j:twitter4j-core:4.1.0'
// Thauvin // Thauvin
implementation 'net.thauvin.erik:cryptoprice:1.0.0' implementation 'net.thauvin.erik:cryptoprice:1.0.0'

View file

@ -43,6 +43,7 @@
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$3600</ID> <ID>MagicNumber:WorldTime.kt$WorldTime.Companion$3600</ID>
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$60</ID> <ID>MagicNumber:WorldTime.kt$WorldTime.Companion$60</ID>
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$86.4</ID> <ID>MagicNumber:WorldTime.kt$WorldTime.Companion$86.4</ID>
<ID>MaxLineLength:TwitterOAuth.kt$TwitterOAuth$*</ID>
<ID>NestedBlockDepth:Addons.kt$Addons$fun add(command: AbstractCommand)</ID> <ID>NestedBlockDepth:Addons.kt$Addons$fun add(command: AbstractCommand)</ID>
<ID>NestedBlockDepth:Addons.kt$Addons$fun add(module: AbstractModule)</ID> <ID>NestedBlockDepth:Addons.kt$Addons$fun add(module: AbstractModule)</ID>
<ID>NestedBlockDepth:Comment.kt$Comment$override fun commandResponse(channel: String, args: String, event: GenericMessageEvent)</ID> <ID>NestedBlockDepth:Comment.kt$Comment$override fun commandResponse(channel: String, args: String, event: GenericMessageEvent)</ID>
@ -58,11 +59,13 @@
<ID>NestedBlockDepth:Seen.kt$Seen$override fun commandResponse(channel: String, args: String, event: GenericMessageEvent)</ID> <ID>NestedBlockDepth:Seen.kt$Seen$override fun commandResponse(channel: String, args: String, event: GenericMessageEvent)</ID>
<ID>NestedBlockDepth:StockQuote.kt$StockQuote.Companion$@JvmStatic @Throws(ModuleException::class) fun getQuote(symbol: String, apiKey: String?): List&lt;Message&gt;</ID> <ID>NestedBlockDepth:StockQuote.kt$StockQuote.Companion$@JvmStatic @Throws(ModuleException::class) fun getQuote(symbol: String, apiKey: String?): List&lt;Message&gt;</ID>
<ID>NestedBlockDepth:Tell.kt$Tell$fun send(event: GenericUserEvent)</ID> <ID>NestedBlockDepth:Tell.kt$Tell$fun send(event: GenericUserEvent)</ID>
<ID>NestedBlockDepth:TwitterOAuth.kt$TwitterOAuth$@JvmStatic @Throws(TwitterException::class, IOException::class) fun main(args: Array&lt;String&gt;)</ID> <ID>NestedBlockDepth:TwitterOAuth.kt$TwitterOAuth$@JvmStatic fun main(args: Array&lt;String&gt;)</ID>
<ID>NestedBlockDepth:Utils.kt$Utils$@JvmStatic fun loadData(file: String, default: Any, logger: Logger, description: String): Any</ID> <ID>NestedBlockDepth:Utils.kt$Utils$@JvmStatic fun loadData(file: String, default: Any, logger: Logger, description: String): Any</ID>
<ID>NestedBlockDepth:Utils.kt$Utils$@JvmStatic fun saveData(file: String, data: Any, logger: Logger, description: String)</ID> <ID>NestedBlockDepth:Utils.kt$Utils$@JvmStatic fun saveData(file: String, data: Any, logger: Logger, description: String)</ID>
<ID>NestedBlockDepth:Weather2.kt$Weather2$override fun run(channel: String, cmd: String, args: String, event: GenericMessageEvent)</ID> <ID>NestedBlockDepth:Weather2.kt$Weather2$override fun run(channel: String, cmd: String, args: String, event: GenericMessageEvent)</ID>
<ID>NestedBlockDepth:Weather2.kt$Weather2.Companion$@JvmStatic @Throws(ModuleException::class) fun getWeather(query: String, apiKey: String?): List&lt;Message&gt;</ID> <ID>NestedBlockDepth:Weather2.kt$Weather2.Companion$@JvmStatic @Throws(ModuleException::class) fun getWeather(query: String, apiKey: String?): List&lt;Message&gt;</ID>
<ID>PrintStackTrace:TwitterOAuth.kt$TwitterOAuth$ioe</ID>
<ID>PrintStackTrace:TwitterOAuth.kt$TwitterOAuth$te</ID>
<ID>ReturnCount:Addons.kt$Addons$fun exec(channel: String, cmd: String, args: String, event: GenericMessageEvent): Boolean</ID> <ID>ReturnCount:Addons.kt$Addons$fun exec(channel: String, cmd: String, args: String, event: GenericMessageEvent): Boolean</ID>
<ID>ReturnCount:Addons.kt$Addons$fun help(channel: String, topic: String, event: GenericMessageEvent): Boolean</ID> <ID>ReturnCount:Addons.kt$Addons$fun help(channel: String, topic: String, event: GenericMessageEvent): Boolean</ID>
<ID>ReturnCount:ExceptionSanitizer.kt$ExceptionSanitizer$fun ModuleException.sanitize(vararg sanitize: String): ModuleException</ID> <ID>ReturnCount:ExceptionSanitizer.kt$ExceptionSanitizer$fun ModuleException.sanitize(vararg sanitize: String): ModuleException</ID>

View file

@ -31,14 +31,15 @@
*/ */
package net.thauvin.erik.mobibot package net.thauvin.erik.mobibot
import twitter4j.AccessToken
import twitter4j.OAuthAuthorization
import twitter4j.TwitterException import twitter4j.TwitterException
import twitter4j.TwitterFactory
import twitter4j.auth.AccessToken
import java.io.BufferedReader import java.io.BufferedReader
import java.io.IOException import java.io.IOException
import java.io.InputStreamReader import java.io.InputStreamReader
import kotlin.system.exitProcess import kotlin.system.exitProcess
/** /**
* The `TwitterOAuth` class. * The `TwitterOAuth` class.
* *
@ -51,7 +52,7 @@ import kotlin.system.exitProcess
* and follow the prompts/instructions. * and follow the prompts/instructions.
* *
* @author [Erik C. Thauvin](https://erik.thauvin.net) * @author [Erik C. Thauvin](https://erik.thauvin.net)
* @author [Twitter4J Example](https://twitter4j.org/en/code-examples.html#oauth) * @author [Yusuke Yamamoto](https://github.com/Twitter4J/Twitter4J/blob/main/twitter4j-examples/src/main/java/examples/oauth/GetAccessToken.java)
*/ */
object TwitterOAuth { object TwitterOAuth {
/** /**
@ -60,49 +61,55 @@ object TwitterOAuth {
* @param args The consumerKey and consumerSecret should be passed as arguments. * @param args The consumerKey and consumerSecret should be passed as arguments.
*/ */
@JvmStatic @JvmStatic
@Throws(TwitterException::class, IOException::class)
fun main(args: Array<String>) { fun main(args: Array<String>) {
if (args.size == 2) { if (args.size == 2) {
with(TwitterFactory.getSingleton()) { try {
setOAuthConsumer(args[0], args[1]) val oAuthAuthorization = OAuthAuthorization.getInstance(args[0], args[1])
val requestToken = oAuthRequestToken val requestToken = oAuthAuthorization.oAuthRequestToken
var accessToken: AccessToken? = null var accessToken: AccessToken? = null
BufferedReader(InputStreamReader(System.`in`)).use { br -> val br = BufferedReader(InputStreamReader(System.`in`))
while (null == accessToken) { while (null == accessToken) {
print( print(
""" """
Open the following URL and grant access to your account: Open the following URL and grant access to your account:
${requestToken.authorizationURL} ${requestToken.authorizationURL}
Enter the PIN (if available) or just hit enter. [PIN]: """.trimIndent() Enter the PIN (if available) or just hit enter. [PIN]: """.trimIndent()
) )
val pin = br.readLine() val pin = br.readLine()
try { try {
accessToken = if (!pin.isNullOrEmpty()) { accessToken = if (!pin.isNullOrEmpty()) {
getOAuthAccessToken(requestToken, pin) oAuthAuthorization.getOAuthAccessToken(requestToken, pin)
} else { } else {
oAuthAccessToken oAuthAuthorization.getOAuthAccessToken(requestToken)
} }
println( } catch (te: TwitterException) {
""" if (401 == te.statusCode) {
Please add the following to the bot's property file: println("Unable to get the access token.")
} else {
twitter-consumerKey=${args[0]} te.printStackTrace()
twitter-consumerSecret=${args[1]}
twitter-token=${accessToken?.token}
twitter-tokenSecret=${accessToken?.tokenSecret}
""".trimIndent()
)
} catch (te: TwitterException) {
if (401 == te.statusCode) {
println("Unable to get the access token.")
} else {
te.printStackTrace()
}
} }
} }
} }
println(
"""
Please add the following to the bot's property file:
twitter-consumerKey=${args[0]}
twitter-consumerSecret=${args[1]}
twitter-token=${accessToken.token}
twitter-tokenSecret=${accessToken.tokenSecret}
""".trimIndent()
)
} catch (te: TwitterException) {
te.printStackTrace()
println("Failed to get accessToken: " + te.message)
exitProcess(-1)
} catch (ioe: IOException) {
ioe.printStackTrace()
println("Failed to read the system input.")
exitProcess(-1)
} }
} else { } else {
println("Usage: ${TwitterOAuth::class.java.name} <consumerKey> <consumerSecret>") println("Usage: ${TwitterOAuth::class.java.name} <consumerKey> <consumerSecret>")

View file

@ -33,9 +33,9 @@ package net.thauvin.erik.mobibot.modules
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.thauvin.erik.jokeapi.JokeApi.Companion.getJoke
import net.thauvin.erik.jokeapi.exceptions.HttpErrorException import net.thauvin.erik.jokeapi.exceptions.HttpErrorException
import net.thauvin.erik.jokeapi.exceptions.JokeException import net.thauvin.erik.jokeapi.exceptions.JokeException
import net.thauvin.erik.jokeapi.getJoke
import net.thauvin.erik.jokeapi.models.Type import net.thauvin.erik.jokeapi.models.Type
import net.thauvin.erik.mobibot.Utils.bot import net.thauvin.erik.mobibot.Utils.bot
import net.thauvin.erik.mobibot.Utils.colorize import net.thauvin.erik.mobibot.Utils.colorize
@ -93,7 +93,7 @@ class Joke : ThreadedModule() {
fun randomJoke(): List<Message> { fun randomJoke(): List<Message> {
return try { return try {
val messages = mutableListOf<Message>() val messages = mutableListOf<Message>()
val joke = getJoke(safe = true, type = Type.SINGLE) val joke = getJoke(safe = true, type = Type.SINGLE, splitNewLine = true)
joke.joke.forEach { joke.joke.forEach {
messages.add(PublicMessage(it, Colors.CYAN)) messages.add(PublicMessage(it, Colors.CYAN))
} }

View file

@ -42,8 +42,6 @@ import org.pircbotx.hooks.types.GenericMessageEvent
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import twitter4j.TwitterException import twitter4j.TwitterException
import twitter4j.TwitterFactory
import twitter4j.conf.ConfigurationBuilder
import java.util.Timer import java.util.Timer
/** /**
@ -214,20 +212,18 @@ class Twitter : ThreadedModule() {
isDm: Boolean isDm: Boolean
): String { ): String {
return try { return try {
val cb = ConfigurationBuilder().apply { val twitter = twitter4j.Twitter.newBuilder()
setDebugEnabled(true) .prettyDebugEnabled(true)
setOAuthConsumerKey(consumerKey) .oAuthConsumer(consumerKey, consumerSecret)
setOAuthConsumerSecret(consumerSecret) .oAuthAccessToken(token, tokenSecret)
setOAuthAccessToken(token) .build()
setOAuthAccessTokenSecret(tokenSecret)
}
val tf = TwitterFactory(cb.build())
val twitter = tf.instance
if (!isDm) { if (!isDm) {
val status = twitter.updateStatus(message) val status = twitter.v1().tweets().updateStatus(message)
"Your message was posted to https://twitter.com/${twitter.screenName}/statuses/${status.id}" "Your message was posted to https://twitter.com/${
twitter.v1().users().accountSettings.screenName
}/statuses/${status.id}"
} else { } else {
val dm = twitter.sendDirectMessage(handle, message) val dm = twitter.v1().directMessages().sendDirectMessage(handle, message)
dm.text dm.text
} }
} catch (e: TwitterException) { } catch (e: TwitterException) {

View file

@ -33,11 +33,14 @@ package net.thauvin.erik.mobibot.modules
import assertk.all import assertk.all
import assertk.assertThat import assertk.assertThat
import assertk.assertions.doesNotContain
import assertk.assertions.each import assertk.assertions.each
import assertk.assertions.isGreaterThan import assertk.assertions.isGreaterThan
import assertk.assertions.isInstanceOf import assertk.assertions.isInstanceOf
import assertk.assertions.prop
import assertk.assertions.size import assertk.assertions.size
import net.thauvin.erik.mobibot.modules.Joke.Companion.randomJoke import net.thauvin.erik.mobibot.modules.Joke.Companion.randomJoke
import net.thauvin.erik.mobibot.msg.Message
import net.thauvin.erik.mobibot.msg.PublicMessage import net.thauvin.erik.mobibot.msg.PublicMessage
import org.testng.annotations.Test import org.testng.annotations.Test
@ -53,6 +56,7 @@ class JokeTest {
size().isGreaterThan(0) size().isGreaterThan(0)
each { each {
it.isInstanceOf(PublicMessage::class.java) it.isInstanceOf(PublicMessage::class.java)
it.prop(Message::msg).doesNotContain("\n")
} }
} }
} }

View file

@ -1,9 +1,9 @@
#Generated by the Semver Plugin for Gradle #Generated by the Semver Plugin for Gradle
#Tue Oct 04 12:17:53 PDT 2022 #Wed Oct 12 20:03:11 PDT 2022
version.buildmeta=737 version.buildmeta=748
version.major=0 version.major=0
version.minor=8 version.minor=8
version.patch=0 version.patch=0
version.prerelease=rc version.prerelease=rc
version.project=mobibot version.project=mobibot
version.semver=0.8.0-rc+737 version.semver=0.8.0-rc+748