Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ALL twitch.tv issues #5184

Open
PhiZero opened this issue Mar 20, 2019 · 439 comments
Open

ALL twitch.tv issues #5184

PhiZero opened this issue Mar 20, 2019 · 439 comments

Comments

@PhiZero
Copy link

PhiZero commented Mar 20, 2019

URL(s) where the issue occurs

twitch.tv

Describe the issue

Embedded video ads are showing again after the fix from #5138 that lasted until now.

Screenshot(s)

Untitled

Versions

  • Browser/version: Chrome 73.0.3683.75
  • uBlock Origin version: 1.18.0

Settings

Default settings.

Notes

Fix that was pushed as part of issue 5138 worked until a few hours ago, now getting embedded ads again. No changes made between then and now. Maybe a recent filter change broke this, or maybe Twitch patched this workaround?

@lain566
Copy link
Contributor

lain566 commented Mar 20, 2019

The @pixeltris's solution has been broken.

@pixeltris
Copy link
Contributor

pixeltris commented Mar 20, 2019

The next logical step is removing the ad chunks in the stream. This unfortunately can add quite a delay until the actual stream starts. See https://github.com/instance01/Twitch-HLS-AdBlock

EDIT: If you play around with the params to the access_token request there seem to be more workarounds. Probably futile to do so though? Maybe implement something similar to Twitch-HLS-AdBlock and then add any additional workarounds as they are found?

@stoically
Copy link

I've just noticed that the initial request, when entering a stream, to https://usher.ttvnw.net/api/channel/hls/<channelname>.m3u8 (serves the playlists for the different encodings) contains a parameter called show_ads set to true. Might be worth trying to rewrite that one to false.

@TheEnhas
Copy link

The platforms (aside from the regular site) are listed here, but I'm not sure what the actual values to use are for each: https://www.twitch.tv/p/platforms/

Might be worth trying though. I think it's odd that platform being undefined worked (for a while) to prevent ads, which means that was probably the default and that the other values are also meant to enable them. On reddit someone (supposedly) doesn't get ads via FireTV so that one may work.

@pixeltris
Copy link
Contributor

pixeltris commented Mar 20, 2019

@stoically that request includes a "sig" param which looks like a SHA1 based on the length. The json request is probably hashed along with some server side secret so I don't think it's feasible to modify that request.

@TheEnhas there is at least one value which can currently bypass the server_ads thing and avoid ads. But I think with a great certainty if it were added to uBlockOrigin it would get fixed within 24 hours.

@TheEnhas
Copy link

@TheEnhas there is at least one value which can currently bypass the server_ads thing and avoid ads. But I think with a great certainty if it were added to uBlockOrigin it would get fixed within 24 hours.

If it's by design on some platforms to save bandwidth or that already have other ads then I'm not sure if they'd "fix it", but I get the feeling it's more likely that they've just not updated those apps yet to work with the new system and they'll get the ads like everyone else once they do.

@stoically
Copy link

@pixeltris Although you're probably right and the token needs to match the sig, I wanted to at least give it a try - but it seems that the overwritten fetch in twitch-videoad.js never gets called with the request to usher.ttvnw.net. Could the reason for that be that the call is maybe made inside a ServiceWorker? Is there a way for uBO to inject something into ServiceWorkers?

FWIW, I've also tried to redirect the request using the WebExtensions onBeforeRequest API, but that leads to a Network Error in the Twitch player and it also doesn't show the request at all in the Network log. The only reason I can think of that causes this, is that the fetch request.redirect for that request is set to manual and fails for non-200 status.

@pixeltris
Copy link
Contributor

@stoically https://gist.github.com/pixeltris/e659867516ed0be149bf5e9e22d7d6e0 something like this should work (I have been using it for tests, modifying the response on a locally hosted server so I don't have to deal with the pain of javascript).

@stoically
Copy link

That works, thanks. Though rewriting the token params results in the server responding with a 403 error, so you're probably right about the sig.

@pijcab
Copy link

pijcab commented Mar 20, 2019

Hi guys,
Is there a documentation on how to add the sort of snippet @pixeltris is giving us ?
Im a complete noob when it comes to modifying Chrome/Firefox extensions...
Edit : This Twitch ad thing is getting out of hand, if I'm a Twitch Prime user I dont want to watch ads on top of that (ads which are usually for services like Amazon Video that are meant for Prime subs...)

@stoically
Copy link

@pijcab Select advanced in the uBO dashboard, click the appearing cog, replace unset for userResourcesLocation with the raw url to the gist (needs a click on raw on the linked gist). This will break all rules which depend on the default resources that are not included in the gist.

@Jap2-0
Copy link

Jap2-0 commented Mar 20, 2019

Wouldn't sig= be generated client-side, or no?

@stoically
Copy link

Yeah, it looks like the sig is generated in the WASM module. Call stack for the request (version 2.9.2):

image

@pijcab
Copy link

pijcab commented Mar 20, 2019

@stoically thank you very much, didn't know that userResourcesLocation was used for that.

Also this might help some people : I found a workaround by using a VPN and connecting to the countries outside of the SureStream available geos (Such as Romania or Hungary).
Didn't get any ads for an hour or two as of now

@TheEnhas
Copy link

TheEnhas commented Mar 20, 2019

Some people reportedly had success by changing their browser's user agent to Android while on Twitch. I tried it and ads still got through.

@pixeltris
Copy link
Contributor

https://gist.githubusercontent.com/pixeltris/e2d4194d7fd5bfa1df39470cb589a012/raw/523c2fa60547046bbd15122e5aa70489f5d8afde/twitch_hls_test.js this is a rough copy/paste of @instance01's https://github.com/instance01/Twitch-HLS-AdBlock for uBlock Origin. Last time I tested his extension I was getting reasonable load times (~5 seconds). Currently everything seems to take like 30+ seconds to load. I haven't looked too much into it yet and had to gut out some code which was causing spam requests.

I tried making a "loading screen" .ts file but failed miserably. If anyone knows how to make a valid .ts file Twitch can load that would be useful. There is a base64 string where the .ts file should go at the bottom of that file. Otherwise the screen will be black for ~30 seconds while ads are displayed.

@TheEnhas
Copy link

TheEnhas commented Mar 20, 2019

Is there a value set anywhere that tells Twitch that you've seen an ad recently so as to not play another one? Because (one big thing I hate about the new pre-roll system) you end up behind the stream once the ad finishes and have to pause/play or reset the player to get back to the right latency, and you don't get another ad right away if you do that. Also, even if I reload or change streams after getting an ad I don't tend to get another for some time. This doesn't make a lot of sense because some people report getting an ad every time they load a stream no matter what, but in my case maybe it's setting some value somewhere that expires after like a half hour or whatever amount of stream loads (whichever comes first).

@stoically
Copy link

stoically commented Mar 20, 2019

@TheEnhas The ads are at least geo-aware, if not targeted. So it's probably some server-side logic that decides whether to include ads in your m3u8 playlists or not (hence the name SSAI). Something like: Some IP-ranges (or targeted users if you're logged in) are limited to a Pre-roll Ad every 15minutes, others are not - based on the options chosen by advertisers.

Related or maybe even superseding issue: #1905

@CaelThunderwing
Copy link

likely Ad blocking may break for me on April 2nd (older Amazon Prime/Twitch Prime and i guess? i was grandfathered into having ads disabled as i have even uBlock disabled and still get squat but i disabled since i made affiliate as to not even tempt to breaking contract,) for when i haveto let it expire briefly to renew w/ a gift of prime... Anyway..

maybe look into how Kodi & the twitch plugin does this because no ads play before or during a stream. I have a media center box in my gaming room setup with Kodi 18.1 and latest twitch plugin outside a few edge cases that streams either crash the box or wont load(a kodi fault/plugin fault) i dont get ads whatso ever, with or without logging into my twitch account.

@pixeltris
Copy link
Contributor

pixeltris commented Mar 20, 2019

https://gist.githubusercontent.com/pixeltris/e2d4194d7fd5bfa1df39470cb589a012/raw/0c9f3d988d9cd0ef5f011ad8057a3d50ae23a38c/twitch_hls_test.js updated version of the adapted Twitch-HLS-AdBlock for uBlock Origin. It should load the stream in 5-10 seconds now rather than 30. Not sure about midroll ads though. Actually maybe 10-30 seconds? Pretty bad still.

@TheEnhas
Copy link

TheEnhas commented Mar 20, 2019

Is there any way to get the time length of the ad at the start, immediately skip to the end of that length and mark it as being "viewed" by Twitch so that you end up with very little (if any) downtime?

@pixeltris
Copy link
Contributor

pixeltris commented Mar 20, 2019

@TheEnhas that's essentially what Twitch-HLS-AdBlock / the thing I linked are doing. There is one m3u8 per stream quality, as it polls the m3u8 file, normal stream segments will start showing up. As soon as they are available they are displayed (and all the ad segments removed). Unfortunately there is still quite a delay before the normal stream is available. Maybe you could spam the m3u8 some more but I doubt it would help.

@stoically
Copy link

Just realized that the token and sig in the /<channelname>.m3u8 request are the exact return values from the initial call to /access_token, so yeah, @pixeltris's assumption of server-side hashing is correct.

@pixeltris Regarding Pre-rolls, the m3u8 requests for me look like this when loading the stream:

  • First Ad:
    • Request time: "Wed, 20 Mar 2019 14:48:47 GMT"
    • m3u8 value: #EXT-X-PROGRAM-DATE-TIME:2019-03-20T14:48:35.822Z
  • First non-Ad (after SCTE35-IN):
    • Request time: "Wed, 20 Mar 2019 14:48:53 GMT"
    • m3u8 value: #EXT-X-PROGRAM-DATE-TIME:2019-03-20T14:48:49.822Z

So the Ad plays 14seconds but the first actual stream .ts is served after 6seconds. However, I think that the m3u8 also includes .ts segments which only will be made available in the future and are not directly available when included in the m3u8 (30-60seconds m3u8 segments vs 2-5seconds stream-delay). I guess the twitch player uses the #EXT-X-PROGRAM-DATE-TIME and that could somehow be rewritten accordingly for the first available non-Ad. Here's the raw HAR for the Pre-roll.

Stripping segments completely works for Pre-rolls, since the player didn't start yet and will start correctly with the first non-Ad segment - but it will break for Mid-rolls because the player already started and suddenly doesn't get segments anymore. Also it seems that Mid-rolls don't serve non-Ad segments early. (More information about my Mid-roll findings including attempts to create a placeholder .ts with ffmpeg are here)

Would be interesting to see other HAR's for Pre-rolls and Mid-rolls (here's how to obtain one: Firefox / Chrome).

@pixeltris
Copy link
Contributor

I'm not sure you can completely strip the m3u8 of all segment files as otherwise the twitch player will start spamming the server hard until it finds something to play. That's why I inserted a dummy .ts entry when there are only ads (it would be ideal if this would be an actual .ts file which displays a message about ads being blocked). Does the current solution I linked break when midrolls are played? I haven't had a chance to see a stream that has played midrolls. Is there a streamer who plays them often?

@pijcab
Copy link

pijcab commented Mar 20, 2019

@pixeltris try Shroud

@stoically
Copy link

@pixeltris

I'm not sure you can completely strip the m3u8 of all segment files as otherwise the twitch player will start spamming the server hard until it finds something to play.

It seems as long as the m3u8 can get parsed (request result not empty), it will not result in the "Invalid variant" error and spam, but rather poll normally.

it would be ideal if this would be an actual .ts file which displays a message about ads being blocked

Did you try the linked ffmpeg command?

Does the current solution I linked break when midrolls are played? I haven't had a chance to see a stream that has played midrolls. Is there a streamer who plays them often?

Hadn't a chance to test with Mid-rolls yet. I know that /twitchpresents plays them in breaks and they will go live again tomorrow (3/21 10AM PT). But I'm pretty sure it'll break, since the correct #EXT-X-PROGRAM-DATE-TIME's are missing and the player can't play the (not existing) .ts segment.

@PhiZero
Copy link
Author

PhiZero commented Mar 21, 2019

@pixeltris

I tried your solution with a stream that does frequent mid-rolls, and it broke the feed. After switching tabs it restarted again when I switched back, but I think that's unrelated. It works fine for pre-rolls however.

@pixeltris
Copy link
Contributor

pixeltris commented Mar 21, 2019

https://gist.githubusercontent.com/pixeltris/e2d4194d7fd5bfa1df39470cb589a012/raw/ddffe9cfabcf881a028a4a813817ade96f6bad17/twitch_hls_test.js this version should display a message in the top left corner "uBlock Origin is waiting for ads to finish..." and the stream should also now continue after midroll ads finish (though the video feed will freeze until the next stream segment is available, I could possibly modify it to go to black or something?).

I might strip out some of the changes I made to support displaying custom .ts files as it really isn't necessary. But besides from that I think it should be good enough?

@stoically Twitch seems to be very finicky about what it can load, I couldn't get anything from ffmpeg or vlc's convert tool to work.

EDIT: https://gist.githubusercontent.com/pixeltris/e2d4194d7fd5bfa1df39470cb589a012/raw/58cf8f1e503f3b5323daf6c12caf986decc86e5e/twitch_hls_test.js this one should be a tiny bit smoother when midrolls play. Live segments take a while to show up during midrolls which is unfortunate. Also I think there is currently some issue when midrolls finish where it skips a couple of segments (possibly due to the sequence modifications). I have noticed that during some hours of the day simply refreshing can result in no ads so it might be possible to spam the access_token request until the result is ad-free (this would require a poll to access_token, followed by the main m3u8, then finally the stream m3u8 to see if ads there or not).

@stoically
Copy link

stoically commented Mar 21, 2019

@pixeltris Works fine for Pre-roll ads - have yet to test with Mid-rolls, I'll let you know. Though it might lead to unexpected behavior when switching streams, since self.seq and the other self assigned variables keep their values (related: instance01/Twitch-HLS-AdBlock#12).

To generate playable placeholder .ts segments, it seems necessary to include a valid "timed metadata" (timed_id3) stream. Here's some Pre-roll debug output from ffprobe for 8 initial ad segments and 2 following live segments - including their corresponding m3u8 entries and the raw timed_id3 header.

@pixeltris
Copy link
Contributor

I've found streams under the "Always On" directory are a good resource for midroll ads (they show ads every 10 minutes or so). Is there a suitable place to reset self values?

@stephenhawk8054
Copy link
Member

Yes, if the new line in replaced part is tricky, we can try to tweak the matched part. This is a test anyways, we don't need to complicate the code more.

@uBlock-user
Copy link
Contributor

@stephenhawk8054 No more auto freeze or pause freeze of the player with ||hls.ttvnw.net/v1/playlist$xhr,3p,replace=/#EXT-X-DATERANGE:ID="(stitched-ad|maf-ad|source|trigger)"\S+\n|#EXT-X-DATERANGE:ID=\S+?CLASS="twitch-(?:stream-source|trigger|maf-ad)"\S+\n|#EXT-X-DATERANGE:\S+?CLASS="twitch-ad-quartile".+?(?=(#EXT-X-DATERANGE|$))|(\n#EXT-X-DISCONTINUITY\s|#EXT-X-TWITCH-PREFETCH\S+)//gs

@stephenhawk8054
Copy link
Member

Oh, so you don't remove assignment and session?

@stephenhawk8054
Copy link
Member

@uBlock-user
Copy link
Contributor

I made two changes to my filter -

  • Add trailing " after "(stitched-ad|maf-ad|source|trigger)
  • Add \s after \n#EXT-X-DISCONTINUITY

You can experiment and check which one of the two helps fixes the freeze issue.

@uBlock-user
Copy link
Contributor

I still see offline issue though: https://github.com/uBlockOrigin/uAssets/assets/66517106/1f516f69-4a66-42b3-a260-e4efde290777

Add these --

www.twitch.tv##.follow-panel-overlay,.tw-media-card-stat
www.twitch.tv##div[class="Layout-sc-1xcs6mc-0"][hidden=""]:style(display:block !important)

We remove everything so twitch thinks stream is offline, unavoidable unless we decide to replace instead of removing stuff incrementally, which I don't know how to.

@stephenhawk8054
Copy link
Member

"player-core-variant-a"

@MostlyJustBored
Copy link

weird, I wonder why it switched over from player-core-base and what these other 2 are

@Janmm14
Copy link

Janmm14 commented Nov 11, 2023

const SEARCH_LOW_QUALITY = /#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="(480p30|360p30|160p30)"[\w\W]+?(?=#EXT-X-MEDIA|$)/g;

6

You can remove the low quality streams which improves the reload times, this information gets sent very early

So if you block cookies it won't default to 360p

https://addons.mozilla.org/en-US/firefox/addon/block-twitch-ads/

That'd not be something for ublock origin to do

@uBlockOrigin uBlockOrigin deleted a comment Nov 17, 2023
@dupraz6482
Copy link

dupraz6482 commented Nov 23, 2023

Prerequisites

  • This is a Twitch report.
  • I read and understand the policy about what is a valid filter issue.
  • I verified that this issue is not a duplicate. (I'll admit I have not read the 400 posts-long thread)
  • I forced an update of my filter lists.
  • I did not remove any of the default filter lists, or I have verified that the issue was not caused by removing any of the default lists.
  • I did not enable additional filter lists, or I have verified that the issue still occurs without enabling additional filter lists.
  • I do not have custom filters/rules, or I have verified that the issue still occurs without custom filters/rules.
  • I am not using uBlock Origin (uBO) along with other content blocker extensions.
  • I have verified that the web browser's built-in blocker or DNS blocking (standalone or through a VPN) is not causing the issue.
  • I did not answer truthfully to ALL the above checkpoints.

URL address of the web page

https://www.twitch.tv/mgg_fr
https://www.twitch.tv/summit1g
https://www.twitch.tv/clix

Note on reproducibility: Only seems to happen on some live channels' homepage (however picking a popular one from the directory is a fair bet), but I have no clear idea about the Twitch heuristic for triggering this and might as well be random

Category

ads

Description

Un-skippable full-screen video advertisement.

Other extensions used

none

Screenshot(s)

Screenshot(s)

1700715333492

Configuration

Tested on: Firefox Release 120.0, Firefox ESR 115.5.0, Chrome Stable 119.0.6045.160 (default settings)
Version: 1.53.0 (default settings, force purged & refreshed)

Details
uBlock Origin: 1.53.0
Firefox: 120
filterset (summary):
 network: 103602
 cosmetic: 43859
 scriptlet: 19007
 html: 1107
listset (total-discarded, last-updated):
 default:
  user-filters: 0-0, never
  ublock-filters: 36579-123, 4m
  ublock-badware: 7483-10, 4m
  ublock-privacy: 729-0, 4m
  ublock-unbreak: 2197-1, 4m
  ublock-quick-fixes: 195-2, 4m
  easylist: 75640-702, 4m
  easyprivacy: 32960-730, 4m
  urlhaus-1: 9790-0, 4m
  plowe-0: 3719-1, 4m
filterset (user): [empty]
userSettings: [none]
hiddenSettings: [none]
supportStats:
 allReadyAfter: 477 ms
 maxAssetCacheWait: 174 ms

Sorry, something went wrong.

@ToxiClay
Copy link

@stephenhawk8054 No more auto freeze or pause freeze of the player with ||hls.ttvnw.net/v1/playlist$xhr,3p,replace=/#EXT-X-DATERANGE:ID="(stitched-ad|maf-ad|source|trigger)"\S+\n|#EXT-X-DATERANGE:ID=\S+?CLASS="twitch-(?:stream-source|trigger|maf-ad)"\S+\n|#EXT-X-DATERANGE:\S+?CLASS="twitch-ad-quartile".+?(?=(#EXT-X-DATERANGE|$))|(\n#EXT-X-DISCONTINUITY\s|#EXT-X-TWITCH-PREFETCH\S+)//gs

UBO says this has an error when I slap it in. I'm not sure where it's telling me the error is, though.

Have we figured out a combination of My Filters and userResourcesLocation that works yet? This comment thread is beyond me, I'm afraid.

@MasterKia
Copy link
Member

UBO says this has an error when I slap it in

Add user- to trustedListPrefixes in "Advanced settings".

@ToxiClay
Copy link

ToxiClay commented Nov 23, 2023

It's now set to

trustedListPrefixes ublock-, user-

and it's still showing an error.
image

Edit:
image

@MasterKia
Copy link
Member

MasterKia commented Nov 23, 2023

It should be:
ublock- user-

Also, use uBO version 1.54.1b0 or higher and Firefox.

@ToxiClay
Copy link

Yeah I'm probably going to have to switch over to Firefox pretty soon with the update to Manifestv3 rolling out, as much as I dread the notion. Maybe the version bump to 1.54 is why it keeps throwing an error, too.

@stephenhawk8054
Copy link
Member

@ToxiClay It throws error because you put ublock-, user-, use ublock- user- as suggested. It's only available on version 1.54+ and Firefox, chromium cannot use this

@ToxiClay
Copy link

@ToxiClay It throws error because you put ublock-, user-, use ublock- user- as suggested. It's only available on version 1.54+ and Firefox, chromium cannot use this

Roger that. Are you guys using Firefox Developer Edition too, then? Regular Firefox won't let me install 1.54.0 because it's unsigned, despite me switching the setting off.

@stephenhawk8054
Copy link
Member

@ToxiClay It's waiting for review from AMO. You can wait until the review finished and it's up on AMO or you can install dev build: https://github.com/gorhill/uBlock/releases/tag/1.54.1b0

@ToxiClay
Copy link

Ahhh, okay. Understood; I'll keep an eye on AMO for 1.54 to go live, make those two mods, and see if it finally fixes Twitch for me.

This actually will legitimately be what pushes me (back) to Firefox; Twitch ads are the absolute devil.

Appreciate your quick responses, @stephenhawk8054.

@stephenhawk8054
Copy link
Member

@ToxiClay Currently we cannot assure which is the solution for twitch ads even with replace yet. The suggested filters can still cause issues.

@ToxiClay
Copy link

Also understood. "This might work" is better than "This definitely doesn't," which is what I'm stuck with now, though!

@uBlock-user
Copy link
Contributor

@ToxiClay I'm using that filter myself and I haven't gotten any other issues, so you should give a try for a fortnight to see how it works for you.

@MostlyJustBored
Copy link

MostlyJustBored commented Nov 24, 2023

const SEARCH_AMAZON_AD_FIRST = /(?:#EXT-X-TWITCH-TOTAL-SECS|#EXT-X-DATERANGE|#EXT-X-START:|#EXT-X-TWITCH-PREFETCH)\S+\n?|#EXT-X-DISCONTINUITY\n?|(?:#EXT-X-TARGETDURATION|#EXT-X-VERSION):[0-9]{0,7}\n?/g;
const SEARCH_AMAZON_AD_SECOND = /#EXT-X-PROGRAM-DATE-TIME:\S+\n?#EXTINF:[0-9]{0,3}.[0-9]{0,7},[^live]+\n?\S+\n?/gs;

@MostlyJustBored
Copy link

const DEBUG_REDUCE = /#EXTM3U\b[\w\W]+?EXT-X-TWITCH-ELAPSED-SECS:\S+\n?/gm;
const DEBUG_REDUCE4 = /#EXT-X-PROGRAM-DATE-TIME:\S+\n?#EXTINF:[0-9]{0,3}.[0-9]{0,7},live+\n\S+\n?/gs;

@ToxiClay
Copy link

@ToxiClay I'm using that filter myself and I haven't gotten any other issues, so you should give a try for a fortnight to see how it works for you.

Well, it seems to love reloading the tab for no explicable reason. This is almost worse than having the ads.

@uBlock-user
Copy link
Contributor

@ToxiClay I'm using that filter myself and I haven't gotten any other issues, so you should give a try for a fortnight to see how it works for you.

Well, it seems to love reloading the tab for no explicable reason. This is almost worse than having the ads.

Disable any twitch related extensions/addons and try again. I get no such occurence on Firefox.

@ToxiClay
Copy link

@ToxiClay I'm using that filter myself and I haven't gotten any other issues, so you should give a try for a fortnight to see how it works for you.

Well, it seems to love reloading the tab for no explicable reason. This is almost worse than having the ads.

Disable any twitch related extensions/addons and try again. I get no such occurence on Firefox.

Good call. While I was fiddling around with Firefox prior to finding the filters here, I had this extension installed which I can't even find anymore. This must have caused the issue. Thanks.
image

@uBlock-user
Copy link
Contributor

I had this extension installed which I can't even find anymore.

@MostlyJustBored Why did you remove your extension from AMO ?

@uBlockOrigin uBlockOrigin deleted a comment Nov 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests