Skip to content

Instantly share code, notes, and snippets.

View fpaint's full-sized avatar

Andrew Afanasyev fpaint

View GitHub Profile
@fpaint
fpaint / api_client.rb
Created October 3, 2023 07:19
My tiny slack client
# frozen_string_literal: true
class Slack::ApiClient
class Error < StandardError; end
API_URL = 'https://slack.com/api'
attr_reader :token
def initialize(token = nil)
@token = token
@fpaint
fpaint / rate_limiter.rb
Created November 24, 2022 15:17
Rate limiter class
# frozen_string_literal: true
# Redis-based rate limiter inspired by a leaking bucket algorithm
class RateLimiter
BUCKET_SIZE = 1000 # arbitrary number, for normalization
BUCKET_MAXIMUM = 5000 # upper limiter of score
TTL = 3600 # expiration time of used keys, to keep the redis clean
OK_RESPONSE = "OK"
COOLDOWN_RESPONSE = "COOLDOWN"
OVERFLOW_RESPONSE = "OVERFLOW"
@fpaint
fpaint / name_matcher.rb
Last active July 10, 2021 05:10
Russian names matcher
class NameMatcher
REGEXP = Regexp.new('^(а(арон|б(а(й|кар|с|т)?|б(ас|ос)|д(и|рахман|у(в(али|охид)|гани|к(арим|одир)|л(а(зиз|тиф)?|л(а(х)?|о(х)?)?|о|хамид|ь)?|малик|р(а(сул|уф|х(им|м(ан|он))|шид)|рахман)|са(л(ам|ом)|мад|ттор))?)|еке|зал|и(дат|л)?|лай(хан)?|о|р(а(м|хам)?|ек|ор(бек)?)?|у(бак(ар|ир|р)|зар|кар)?|ылай(хан)?)?|в(а(з(бек)?|тария)?|густин(а)?|д(ей|отья)|е(л(ина|ь)|т(и(к|с))?)|ик|р(а(ам|м)|елия|ил|ора)|тандил)?|г(а(бек|си|точка|ф(он|ья))|ван|зам|ил(ь)?|лая|н(е(с(а|са)?|шка)?|ия)?|р(афена|ип(ина|пина))|унда)|д(а(й|лят|м)|е(кс(андр(а)?|ей)?|л(аида|ечка|и(н(а|ка|очка)|я)|ь(ка|я)?|я)|м(а|и))?|и(ба|к|л(бек|е(т)?|жан|хан|ь(бек|жан|хан)?|я)?|на(й)?|с(а)?|я)?|л(ан|ет)|мир|о(к|льф)|р(ей|иан(а|о)?)|хам|ы(гжы|л(бек|жан)?)|ьян|эл(ина|ь|я))|е(к(а|с(андр|ей)))?|жар(а)?|з(а(д(а)?|зель|л(и(на|я)|ька)|м(ат|жон)?|р|т)?|ер|и(ана|з(а|бек|жон|ов)?|к|м(а|бек|жон|хан)?|рет|с|яна)?|наур|р(аил|ет))?|и(бек|г(ерим|ул(ь)?)|д(а(на|р)?|о(с|чка)|ын)?|жан|за|ка|ма|н(а|ур)|ша)|й(а(ал|на|ру)|б(а(ну|р|т)?|ек|ике|ол(ат)?|улат|ын)?|ва(з
@fpaint
fpaint / ward.rb
Created October 10, 2019 10:48
Script for downloading Wildbow's "Ward" & generating fb2 book for my reader
require 'nokogiri'
require 'faraday'
require 'date'
require 'digest'
class Ward
BASE = 'https://www.parahumans.net'
class Page
@fpaint
fpaint / fetcher.js.jsx.coffee
Created March 26, 2018 11:52
Component wrapper with async props loading
class @Fetcher extends React.Component
@propTypes:
endpoint: PropTypes.string
content: PropTypes.func
onError: PropTypes.func
constructor: (props)->
super(props)
this.state =
data: this.props.data || null
fetch: ->
class @ModalPage extends React.Component
componentWillMount: ->
$('body').addClass('noscroll')
key.setScope('modal')
key('esc', 'modal', this.props.close)
componentWillUnmount: ->
$('body').removeClass('noscroll')
key.deleteScope('modal')
@fpaint
fpaint / editor.coffee
Created March 29, 2016 20:41
Модуль для форм
App.editor = (->
self =
# ------------------ Форма ------------------
form: (container)->
el = $(container)
# примитивы
init_controls = ->
button = $('<button type=button>').addClass('submit_button').html('Сохранить')
el.append App.template.div 'form_controls', button
@fpaint
fpaint / orh.ajax.coffee
Created September 19, 2015 09:39
Ajax module in my project
window.OrhApp ||= { }
OrhApp.Ajax = (settings) ->
ajax = this
@error_proc = (proc)->
(ctx)->
proc?(ctx).fail (xhr)->
if xhr.status == 404 and match = xhr.responseText.match /^Redirect: (.*)$/
location.href = match[1]
@fpaint
fpaint / gist:971034076a073870982b
Last active August 29, 2015 14:18
Vk Chat cleanup
(function(){
function chat_cleanup(chat_id, blacklist) {
var keep = [], reg_magic = /kickChatMember\((\d+), (\d+), '(\w+)', intval\(\d\), '.*?', '(.*?)'\)/g, match;
ajax.post('al_im.php', {act:'a_show_members_box', al: '1', chat: chat_id}, {onDone: function(title, text) {
while(match = reg_magic.exec(text)) {
var chat = match[1], mid = match[2], hash = match[3], user = match[4];
if(blacklist.indexOf(user)>=0) {
console.log('Kick %s %s %s from chat %s', user, mid, hash, chat);
ajax.post('al_im.php', extend({act: 'a_kick_user', chat: chat, hash: hash, mid: mid}));
} else {keep.push(user);}