mcmxi/dev.md

18 KiB

Notes for development

Various JSON APIs
https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=Craig%20Noone&format=json
https://www.coingecko.com/en/api#
https://api.coingecko.com/api/v3/coins/bitcoin?tickers=true&market_data=true&community_data=true&developer_data=true&sparkline=true
https://searx.everdot.org/?q=hi&categories=general&language=en-US&format=json
https://searx.everdot.org/?q=site%3Atextfiles.com&categories=files&language=en-US&format=json

<form action="https://tinyurl.com/create.php" method="post" target="_blank">
<table align="center" cellpadding="5" bgcolor="#E7E7F7"><tr><td>
<b>Enter a long URL to make <a href="https://tinyurl.com">tiny</a>:</b><br/>
<input type="text" name="url" size="30"><input type="submit" name="submit" value="Make TinyURL!">
</td></tr></table>
</form>

bot API docs and examples
https://github.com/jaraco/irc/blob/master/irc/events.py
https://pypi.org/project/unshare/
https://github.com/docker/docker-py
https://dnspython.readthedocs.io/en/stable/installation.html
https://dnspython.readthedocs.io/en/latest/resolver-class.html
https://github.com/jaraco/irc/blob/71891ea3034067d6678da21bd6d6046ee2d06df5/irc/bot.py#L254

character sets
https://jrgraphix.net/research/unicode_blocks.php

Notes on bs4:
[ meta.attrs['content'] for meta in doc.find_all('meta') if 'name' in meta.attrs and meta.attrs['name'] == 'description' ]
could provide additional info

https://api.coingecko.com/api/v3/coins/bitcoin?tickers=true&market_data=true&community_data=true&developer_data=true&sparkline=true
notes:
from statistics import mean
set([x['market']['name'] for x in b['tickers']])
mean(sorted([x['converted_last']['usd'] for x in b['tickers']]))

In [13]: [ x.attrs for x in HTML(bots[0][0].grab("https://www.youtube.com/watch?v=rvfEldHBnqM"), features = "html.parser").find("head") if type(x) == SOUP.element.Tag if x.attrs.get("property") !
    ...: = None and x.attrs.get("property").startswith("og:") ]
DEBUG|mcmxi->grab https://www.youtube.com/watch?v=rvfEldHBnqM
DEBUG|connectionpool->_new_conn Starting new HTTPS connection (1): www.youtube.com:443
DEBUG|connectionpool->_make_request https://www.youtube.com:443 "GET /watch?v=rvfEldHBnqM HTTP/1.1" 200 None
DEBUG|mcmxi->grab <Response [200]>
Out[13]: 
[{'property': 'og:site_name', 'content': 'YouTube'},
 {'property': 'og:url',
  'content': 'https://www.youtube.com/watch?v=rvfEldHBnqM'},
 {'property': 'og:title', 'content': 'Still A G Thang'},
 {'property': 'og:image',
  'content': 'https://i.ytimg.com/vi/rvfEldHBnqM/maxresdefault.jpg'},
 {'property': 'og:image:width', 'content': '1280'},
 {'property': 'og:image:height', 'content': '720'},
 {'property': 'og:description',
  'content': 'Provided to YouTube by Universal Music Group Still A G Thang · Snoop Dogg The Best Of Snoop Dogg ℗ 1998 Priority Records, LLC Released on: 2005-01-01 Associa...'},
 {'property': 'og:type', 'content': 'video.other'},
 {'property': 'og:video:url',
  'content': 'https://www.youtube.com/embed/rvfEldHBnqM'},
 {'property': 'og:video:secure_url',
  'content': 'https://www.youtube.com/embed/rvfEldHBnqM'},
 {'property': 'og:video:type', 'content': 'text/html'},
 {'property': 'og:video:width', 'content': '960'},
 {'property': 'og:video:height', 'content': '720'},
 {'property': 'og:video:tag', 'content': 'Snoop Dogg'},
 {'property': 'og:video:tag', 'content': 'スヌープ・ドッグ'},
 {'property': 'og:video:tag', 'content': 'スヌープドッグ'},
 {'property': 'og:video:tag', 'content': 'The Best Of Snoop Dogg'},
 {'property': 'og:video:tag', 'content': 'Still A G Thang'},
 {'property': 'og:video:tag', 'content': 'スティル・ア・G・サング'},
 {'property': 'og:video:tag', 'content': 'スティル・ア・ジー・サング'}]

In [23]: (lambda l: [x.attrs for x in HTML(bots[0][0].grab(l), features = "html.parser").find("head") if type(x) == SOUP.element.Tag if x.attrs.get("property") != None and x.attrs.get("property")
    ...: .startswith("og:")])("https://www.microsoft.com")
DEBUG|mcmxi->grab https://www.microsoft.com
DEBUG|connectionpool->_new_conn Starting new HTTPS connection (1): www.microsoft.com:443
DEBUG|connectionpool->_make_request https://www.microsoft.com:443 "GET / HTTP/1.1" 302 0
DEBUG|mcmxi->grab https://www.microsoft.com/en-au/
DEBUG|connectionpool->_new_conn Starting new HTTPS connection (1): www.microsoft.com:443
DEBUG|connectionpool->_make_request https://www.microsoft.com:443 "GET /en-au/ HTTP/1.1" 200 39573
DEBUG|mcmxi->grab <Response [200]>
Out[23]: 
[{'property': 'og:url', 'content': 'https://www.microsoft.com/en-au'},
 {'property': 'og:title', 'content': 'Microsoft - Official Home Page'},
 {'property': 'og:description',
  'content': 'At Microsoft our mission and values are to help people and businesses throughout the world realize their full potential.'},
 {'property': 'og:type', 'content': 'website'}]

In [24]:

In [77]: [ x for x in HTML(bots[0][0].grab("https://imgur.com/a/AjZCl0b"), features="html.parser").find_all("meta") if type(x) == SOUP.element.Tag if x.get("property") != None and x.get("property
    ...: ").startswith("og:")]
DEBUG|mcmxi->grab https://imgur.com/a/AjZCl0b
DEBUG|connectionpool->_new_conn Starting new HTTPS connection (1): imgur.com:443
DEBUG|connectionpool->_make_request https://imgur.com:443 "GET /a/AjZCl0b HTTP/1.1" 200 None
DEBUG|mcmxi->grab <Response [200]>
Out[77]: 
[<meta content="Imgur" property="og:site_name"> <meta content="12331492" property="fb:admins"/> <meta content="12301369" property="fb:admins"/> <meta content="127621437303857" property="fb:app_id"/> <meta content="imgur://imgur.com/?from=fbreferral" property="al:android:url"/> <meta content="Imgur" property="al:android:app_name"/> <meta content="com.imgur.mobile" property="al:android:package"/> <meta content="imgur://imgur.com/?from=fbreferral" property="al:ios:url"/> <meta content="639881495" property="al:ios:app_store_id"/> <meta content="Imgur" property="al:ios:app_name"/> <meta content="https://imgur.com/" property="al:web:url"/> <meta content="@imgur" name="twitter:site"/> <meta content="imgur.com" name="twitter:domain"/> <meta content="com.imgur.mobile" name="twitter:app:id:googleplay"/> <meta content="Imgur" property="author"/> <meta content="Imgur" property="article:author"/> <meta content="https://www.facebook.com/imgur" property="article:publisher"/> <title>Imgur: The magic of the Internet</title><meta content="https://imgur.com/a/AjZCl0b" data-react-helmet="true" property="og:url"/><meta content="https://i.imgur.com/V0jL8lNh.jpg" data-react-helmet="true" name="twitter:image"/><link href="https://api.imgur.com/oembed.json?url=https://imgur.com/a/AjZCl0b" rel="alternate" title="Imgur: The magic of the Internet" type="application/json+oembed"/><link href="https://api.imgur.com/oembed.xml?url=https://imgur.com/a/AjZCl0b" rel="alternate" title="Imgur: The magic of the Internet" type="application/xml+oembed"/><meta href="https://imgur.com/a/AjZCl0b" rel="canonical"/><meta content="600" data-react-helmet="true" property="og:image:width"/><meta content="315" data-react-helmet="true" property="og:image:height"/><meta content="https://i.imgur.com/V0jL8lN.png?fb" data-react-helmet="true" property="og:image"/><meta content="article" data-react-helmet="true" property="og:type"/><meta content="summary_large_image" data-react-helmet="true" name="twitter:card"/><meta content="imgur.com" data-react-helmet="true" name="twitter:title"/><meta content="Imgur: The magic of the Internet" data-react-helmet="true" name="twitter:description"/><meta content="imgur.com" data-react-helmet="true" property="og:title"/><meta content="Imgur: The magic of the Internet" data-react-helmet="true" property="og:description"/> <script>dataLayer=[];var pbjs=pbjs||{};pbjs.que=pbjs.que||[]</script> <script async="true">!function(){var e=document.createElement("script"),t=document.getElementsByTagName("script")[0],n="https://quantcast.mgr.consensu.org".concat("/choice/","f8oruOqDFlMeI","/","imgur.com","/choice.js"),a=0;e.async=!0,e.type="text/javascript",e.src=n,e.onload=function(){var e=document.createEvent("Event");e.initEvent("cmpLoaded",!0,!0),window.dispatchEvent(e)},t.parentNode.insertBefore(e,t),function(){for(var e,i="__tcfapiLocator",a=[],o=window;o;){try{if(o.frames[i]){e=o;break}}catch(e){}if(o===window.top)break;o=o.parent}e||(function e(){var t=o.document,n=!!o.frames[i];if(!n)if(t.body){var a=t.createElement("iframe");a.style.cssText="display:none",a.name=i,t.body.appendChild(a)}else setTimeout(e,5);return!n}(),o.__tcfapi=function(){var e,t=arguments;if(!t.length)return a;if("setGdprApplies"===t[0])3<t.length&&2===t[2]&&"boolean"==typeof t[3]&&(e=t[3],"function"==typeof t[2]&&t[2]("set",!0));else if("ping"===t[0]){var n={gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"};"function"==typeof t[2]&&t[2](n)}else a.push(t)},o.addEventListener("message",function(a){var i="string"==typeof a.data,e={};try{e=i?JSON.parse(a.data):a.data}catch(e){}var o=e.__tcfapiCall;o&&window.__tcfapi(o.command,o.version,function(e,t){var n={__tcfapiReturn:{returnValue:e,success:t,callId:o.callId}};i&&(n=JSON.stringify(n)),a.source.postMessage(n,"*")},o.parameter)},!1))}();var i=function(){var e=arguments;typeof window.__uspapi!==i&&setTimeout(function(){void 0!==window.__uspapi&&window.__uspapi.apply(window.__uspapi,e)},500)};if(void 0===window.__uspapi){window.__uspapi=i;var o=setInterval(function(){a++,window.__uspapi===i&&a<3?console.warn("USP is not accessible"):clearInterval(o)},6e3)}}()</script> <link href="https://s.imgur.com/desktop-assets/css/styles.ebc99cf807f6b7c8c39c.css" rel="stylesheet"/></meta>,
 <meta content="https://imgur.com/a/AjZCl0b" data-react-helmet="true" property="og:url"/>,
 <meta content="600" data-react-helmet="true" property="og:image:width"/>,
 <meta content="315" data-react-helmet="true" property="og:image:height"/>,
 <meta content="https://i.imgur.com/V0jL8lN.png?fb" data-react-helmet="true" property="og:image"/>,
 <meta content="article" data-react-helmet="true" property="og:type"/>,
 <meta content="imgur.com" data-react-helmet="true" property="og:title"/>,
 <meta content="Imgur: The magic of the Internet" data-react-helmet="true" property="og:description"/>]

#NLP

cards

        '''
        clubs (lowest), followed by diamonds, hearts, and spades (highest).
        [(chr(x), x) for x in [9827, 9830, 9829, 9824]]
        [(chr(x), x) for x in [9831, 9826, 9825, 9828]]
        52 card deck
        list(itertools.chain.from_iterable(map(lambda c: [ x for x in [
        (c, "A"),
        (c, "K"),
        (c, "Q"),
        (c, "J"),
        (c, "10"),
        (c, "9"),
        (c, "8"),
        (c, "7"),
        (c, "6"),
        (c, "5"),
        (c, "4"),
        (c, "3"),
        (c, "2") ]
        ], [ chr(x) for x in [0x2660, 0x2661, 0x2666, 0x2667 ] ] ) ) )

        Bridge (for bidding and scoring) and occasionally poker: spades, hearts, diamonds, clubs; 'notrump'
        ranks above all the suits[clarification needed]

        Preferans: hearts, diamonds, clubs, spades. Only used for bidding, and No
        Trump[clarification needed] is considered higher than hearts.
        Five Hundred: hearts, diamonds, clubs, spades (for bidding and scoring)

        Ninety-nine: clubs, hearts, spades, diamonds (supposedly mnemonic as they have
        respectively 3, 2, 1, 0 lobes; see article for how this scoring is used)

        Skat: clubs, spades, hearts, diamonds; or acorns, leaves, hearts, bells
        (for bidding and to determine which Jack beats which in play)
        Big Two: spades, hearts, clubs, diamonds (Presidents reverses suit strength:
        hearts, diamonds, spades, clubs)

        Teen patti: In the case where two players have flushes with cards of the same
        rank, the winning hand is based on suit color as ranked by clubs, hearts, spades, diamonds.
        Thirteen: hearts, diamonds, clubs, spades.

        durak deck:
        
        durak_deck = lambda: [(x, z, ord(x) | rank_value) for x, z, rank_value in itertools.chain.from_iterable(map(lambda c: [ x for x in [ (c,"A", 0x8192), (c, "K", 0x4096), (c, "Q", 0x2048), (c, "J", 0x1024), (c, "10", 0x512), (c, "9", 0x256), (c, "8", 0x128), (c, "7", 0x64), (c, "6", 0x32), (c, "5", 0x16), (c, "4", 0x08), (c, "3", 0x04), (c, "2", 0x02) ] ], [ chr(x) for x in [0x2660, 0x2661, 0x2666, 0x2667 ] ]  ) ) if len([y for y in ["A", "K", "Q", "J", "10", "9", "8", "7", "6"] if y == z]) > 0 ]
        
        players = ["deuce", "spigot", "rands"] 

        current_game_deck = random.sample(durak_deck(), 36)
               
        The game is typically played with two to five people, with six players if desired, using a deck of 36 cards, 
        for example a standard 52-card deck from which the numerical cards 2 through 5 have been removed. 
        In theory the limit for a game with one deck of 36 cards is six players, but this extends a 
        considerable advantage to the player who attacks first, and a considerable disadvantage to the 
        player who defends first. Variants exist that use more than one deck.
        
        durak_deck = players > 6 and durak_deck * 2 or durak_deck (NOTE to self, color offest inverted?) 
        
        The deck is shuffled, and each player is dealt six cards. The bottom card of the stock is 
        turned and placed face up on the table, its suit determining the trump suit for the current deal. 
        For example, if it is the 7 of diamonds, then diamonds rank higher than all plain-suit cards. 
        The rest of the pack is then placed on half over the turnup and at right angles to it, 
        so that it remains visible. These cards form the prikup or talon. The turnup remains part 
        of the talon and is drawn as the last card. Cards discarded due to successful defences are 
        placed in a discard pile next to the talon.
        
        dealer = lambda cards, players: [ cards[y : y + 6 ] for x, y in zip(range(players), [ 0, 6, 12, 18, 24, 30 ] ) ]
        
        hands = dict(zip(players, dealer(current_game_deck, len(players) ) ) )
        
        # note this pack/unpack of the deck in a lambda isn't actually necesarry since the turn up / trump card 
        # is actually considered to be part of the talon and doesn't need to be "popped" but "peeked", 
        # but the example remains for other games where a card maybe selectively removed at the same time that 
        # the stock is assigned:
        
        talon, turn_up = (lambda s: (s, s[ -1 ] ) )(list(itertools.chain.from_iterable(dealer(current_game_deck, 
        6 )[ len(players) : 6 ])))
        
        self.connection.privmsg(target, "trump card is {1}//{0}".format(turn_up))
        
        The player who has the lowest trump card will be the first attacker (note that there is no obligation to 
        play that lowest trump card as the first card). The player to the attacker's left is always the defender. 
        After each round of attack play proceeds clockwise. If the attack succeeds (see below), the defender 
        loses their turn and the attack passes to the player on the defender's left. If the attack fails, 
        the defender becomes the next attacker.
        
        In [63]: turn_up                                                                                                          Out[64]: ('♠', '9', 9846)
        
        next(enumerate(sorted(itertools.chain.from_iterable([[(x, suite, rank, rank_val
        ) for suite, rank, rank_val in hands.get(x) if suite == turn_up[0] ] for x in hands.keys()]
        ), key = lambda k: k[3])))
        
        Out[65]: (0, ('deuce', '♠', '6', 9842))
        
        for reference the hands in this game are: 
        
        { 'deuce': [
        ('♡', 'A', 42995),
        ('♦', 'J', 13926),
        ('♠', 'J', 13924),            <-- trump 
        ('♡', '6', 9843),
        ('♧', 'A', 42999),
        ('♠', '6', 9842)],            <-- trump (lowest)
        'spigot': [
        ('♦', 'A', 42998),
        ('♡', 'J', 13925),
        ('♡', 'Q', 9833),
        ('♡', '7', 9829),
        ('♦', '10', 10102),
        ('♧', 'J', 13927)],
        'rands': [
        ('♦', '8', 10094),
        ('♧', '8', 10095),
        ('♦', '7', 9830),
        ('♦', 'K', 26358),
        ('♧', 'K', 26359),
        ('♧', '6', 9847)] }
        
        Cards are ranked 6 7 8 9 10 J Q K A. A trump card of any rank beats all cards in the other three suits. 
        For example, a 6 of trumps beats an ace of any other suit.
        
        The attacker opens their turn by playing a card face up on the table as an attacking card. The player to the 
        attacker's left is the defender. They respond to the attack with a defending card.
        
        
        

Chess

cracked out chess board

(lambda l: [y for y, _, _ in [(l[x], l[x].append(chr(ord(l[x][1]) + 6)), l[x].append(chr(ord(l[x][0]) + 6))) for x in l]])(dict(list(zip(["a", "b", "c", "d", "e", "f", "g", "h"], [[chr(0x2656), chr(0x2659)] + [None] * 4, [chr(0x2658), chr(0x2659)] + [None] * 4, [chr(0x2657), chr(0x2659)] + [None] * 4, [chr(0x2655), chr(0x2659)] + [None] * 4, [chr(0x2654), chr(0x2659)] + [None] * 4, [chr(0x2657), chr(0x2659)] + [None] * 4, [chr(0x2658), chr(0x2659)] + [None] * 4, [chr(0x2656), chr(0x2659)] + [None] * 4] ) ) ) )

more notes

In [12]: test = JSON.loads(bots[0][0].grab("https://en.wikipedia.org/w/api.php?action=query
    ...: &list=search&srsearch=wtf&format=json") )
I-search backward: test =

In [11]: next(enumerate(test.get("query").get("search")))
Out[11]: 
(0,
 {'ns': 0,
  'title': 'WTF',
  'pageid': 423373,
  'size': 2534,
  'wordcount': 333,
  'snippet': '<span class="searchmatch">WTF</span> usually refers to: &quot;What the fuck?&quot;, an expression of disbelief <span class="searchmatch">WTF</span> may also refer to: Work Time Fun, a video game for the PlayStation Portable WTF',
  'timestamp': '2020-08-04T23:25:04Z'})

In [12]:

executables notes

(M,
"",
lambda target, event, instance: self.connection.privmsg(
target,
self.is_func_or_meth(instance)
and (_ for _ in ()
).throw(Exception("only property references allowed") )
or str(instance) ) ),
(STAT,
"",
lambda target, event, instance: self.connection.privmsg(
target,
self.is_func_or_meth(instance)
and (_ for _ in ()
).throw(Exception("only property references allowed") )
or str(instance) ) ),