Last active
November 10, 2017 13:19
-
-
Save travisbrown/71eddd5d4dc266decf096b02fabba1ab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cats.data.StateT | |
import cats.implicits._ | |
import scala.collection.JavaConverters._ | |
import scala.concurrent.{Await, Future} | |
import scala.concurrent.ExecutionContext.Implicits.global | |
import scala.concurrent.duration.Duration | |
import twitter4j._, twitter4j.conf.ConfigurationBuilder | |
object YourTweetsAreTooLong { | |
private type PagingState = (Long, Option[Long]) | |
private type OffenderState = (PagingState, Map[String, Set[Long]]) | |
private type S[x] = StateT[Future, OffenderState, x] | |
private val config = new ConfigurationBuilder().setTweetModeExtended(true) | |
private val client: Twitter = new TwitterFactory(config.build).getInstance() | |
private val strikes = 3 | |
private val threshold = 200 | |
def isBad(status: Status): Boolean = status.getText.length > threshold | |
val nextBatch: StateT[Future, PagingState, List[Status]] = StateT { | |
case (timeToWait, lastId) => | |
val paging = lastId.fold(new Paging(1, 200))(new Paging(1, 200, _)) | |
Future { | |
Thread.sleep(timeToWait) | |
client.getHomeTimeline(paging) | |
}.map { result => | |
val remaining = result.getRateLimitStatus.getRemaining | |
val nextTimeToWait = if (remaining > 0) 60000L else { | |
result.getRateLimitStatus.getSecondsUntilReset * 1000L | |
} | |
val statuses = result.asScala.toList | |
((nextTimeToWait, statuses.headOption.map(_.getId)), statuses) | |
} | |
} | |
val unfollow: S[Unit] = nextBatch | |
.transformS[OffenderState](_._1, (t, o) => (o, t._2)) | |
.transform { | |
case ((state, offenders), statuses) => | |
val newOffenders = offenders |+| statuses | |
.filter(isBad) | |
.groupBy(_.getUser.getScreenName) | |
.mapValues(_.map(_.getId).toSet) | |
((state, newOffenders), newOffenders) | |
}.flatMapF { | |
_.toList.filter(_._2.size >= strikes).map(_._1).traverse_ { user => | |
Future { | |
println(s"so long $user") | |
client.destroyFriendship(user) | |
} | |
} | |
} | |
def main(args: Array[String]): Unit = Await.result( | |
unfollow.iterateWhile(_ => true).run(((0L, None), Map.empty)), | |
Duration.Inf | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment